Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to go back from calling intent

I call camera to take a picture. But I cannot go back to my own original activity after taking the picture. What's the problem? Thank you.

    public void addEntry(View view)
{
              String EntryName=RegisterName.toString();
              Toast.makeText(this, EntryName, Toast.LENGTH_LONG);
              Intent addEntryintent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
              File file = new File(getFilesDir(),EntryName);
              registeryFileUri = Uri.fromFile(file);
              addEntryintent.putExtra(MediaStore.EXTRA_OUTPUT, registeryFileUri);
              startActivityForResult(addEntryintent,TAKE_PICTURE);         

}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == TAKE_PICTURE) 
      {
          if (data != null)
          {   
         Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
         ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
         Registerimage.setImageURI(registeryFileUri);
         }

    }
  }
like image 644
James Avatar asked Nov 22 '11 04:11

James


3 Answers

It took me a while to get it working and I have made several things and finally it works. I can't tell certainly which of the things I did is the solution to the problem, but they all together form the working solution.

There are multiple reasons why the camera activity does not return back. Two major ones are:

  1. path for the new picture is invalid, or non-existing, or it can't be created

  2. application got suspended and saved path get lost.

So here is my code solving all these problems, all together working.

First I created helper class ImageServices:

class ImageServices {

  private static String getTempDirectoryPath(Context ctx) {
    File cache;

    // SD Card Mounted
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
      cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
              "/Android/data/" + ctx.getPackageName() + "/cache/");
    }
    // Use internal storage
    else {
      cache = ctx.getCacheDir();
    }

    // Create the cache directory if it doesn't exist
    if (!cache.exists()) {
      cache.mkdirs();
    }

    return cache.getAbsolutePath(); 
  }

  public static Uri getOutputImageFileUri(Context ctx) {
    // TODO: check the presence of SDCard

    String tstamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File file = new File(getTempDirectoryPath(ctx), "IMG_" + tstamp + ".jpg");

    return Uri.fromFile(file);

  }
}

The code is partially inspired by developer.android.com and partially by CameraLauncher class of Apache Cordova project.

In my activity the event handler for button to take a picture looks like this:

private Uri imageFileUri;

private static final int MAKE_PHOTO_RESULT_CODE = 100;
private static final int PICK_PHOTO_RESULT_CODE = 101;

public void onMakePhoto(View v) {
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  imageFileUri = ImageServices.getOutputImageFileUri(this);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
  Log.i("babies", "Taking picture: requested " + imageFileUri);
  startActivityForResult(intent, MAKE_PHOTO_RESULT_CODE);
}

Method onActivityResult does not really contain much, as imageFileUri already points to the existing file and necessary rendering is done in onResume method, which is called when the activity gets back into foreground:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (resultCode == RESULT_OK) {
    switch(requestCode) {
      case MAKE_PHOTO_RESULT_CODE:
        assert imageFileUri != null;
        break;
      case ...
        ...other cases...
        break;
    }
  }
}

But this is still not sufficient, as imageFileUri gets lost as your app gets suspended. And on regular device the chances are close to 100%. So next you need to store the value of imageFileUri to instance state:

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  if (imageFileUri == null) {
    outState.putString("file-uri", "");
  }
  else {
    outState.putString("file-uri", imageFileUri.toString());
  }
};

and load it again in - easiest is directly in onCreate:

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  if (savedInstanceState != null) {
    String fileUri = savedInstanceState.getString("file-uri");
    if (!fileUri.equals("")) imageFileUri = Uri.parse(fileUri);
  }
}

So, again, on top of many other solutions presented on this site as well as elsewhere, there are two major differences:

  1. smarter getTempDirectoryPath inspired by Apache Cordova
  2. allowing imageFileUri to survive suspended application

And now - at least for me - everything works fine.

like image 185
Tom Burger Avatar answered Sep 28 '22 09:09

Tom Burger


Answer

Use appContext.getExternalCacheDir() and don't forget to mention permissons.

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
              if (requestCode == TAKE_PICTURE) 
              {
                      if(resultCode==Activity.RESULT_OK)
                  { //if (data != null)
                    //{   
                    Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
                    ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
                    Registerimage.setImageURI(registeryFileUri);
                    //}
                       }
                      else
                         Toast.makeText(this, "Not Registered!", Toast.LENGTH_LONG);
             }  
**"android.permission.CAMERA"**     

Check whether the above permission is specified in your manifest or not

Note: It's better to use getExternalCacheDir() than getFilesDir() if you still dont get the 
      image then use that. Dont forgot to specify the permission "android.permission.WRITE_EXTERNAL_STORAGE" if you use the getExternalCacheDir().
like image 40
KK_07k11A0585 Avatar answered Sep 28 '22 10:09

KK_07k11A0585


On some devices data will unfortunately be null in onActivityResult after calling the camera activity. So you may need to save your state in your activity's variables, and them read them in onActivityResult. Be sure to save these variables in onSaveInstanceState and restore them in onCreate.

like image 45
TotoroTotoro Avatar answered Sep 28 '22 08:09

TotoroTotoro