23

So I am aware of the camera's issue on Samsung devices. You need to create a Uri before calling the camera intent like so:

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, m_username);
mImageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

This example creates a Uri for the camera to store the data in. My app has a camera function in two locations. Both are identical (direct copy paste), but in one activity the mImageUri object becomes null during the camera process, while in the other it doesn't. The latter works fine, but the former gives a null value which in turn stops me from saving the image, previewing it, etc. I will provide the onResult code below:

case CAMERA_PIC_REQUEST :
if(resultCode == RESULT_OK) {
    if(intent != null) {
        //For non-Samsung devices
        Log.e("Intent value:", intent.toString());
        mImageUri = intent.getData();
    }

    mAvatar = BitmapStatic.createImage(mImageUri, this);
    Drawable draw = new BitmapDrawable(getResources(), mAvatar);
    m_photoButtonE.setImageDrawable(draw);
    m_imageChanged = true;
}
break;

The above example is from the working activity. Below is the activity where this doesn't work:

//On pressing the "Take Photo" button:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, mUsername);
mImageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if(mImageUri == null) {
    Log.e("image uri is null", "what?");
}
else {
    Log.e("oh nevermind", "image uri is NOT null");
}
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

//On Result:
case CAMERA_PIC_REQUEST :
if(resultCode == RESULT_OK) {
    if(intent != null) {
        Log.e("Intent value:", intent.toString());
        mImageUri = intent.getData();
    }
    else {
        Log.e("Intent is null", "yep it is.");
        if(mImageUri == null) {
            Log.e("nullcheck on memberimageuri", "its null");
        }
        else {
            Log.e("nullcheckon memberimage", mImageUri.toString());
        }
    }
    mImage = BitmapStatic.createImage(mImageUri, this);
    Drawable draw = new BitmapDrawable(getResources(), mImage);
    mPhotoPreview.setImageDrawable(draw);
}
break;

Notice the log files I have put in this 2nd example. When I click the "Take Picture" button, the null check for the mImageUri object returns true. So this object is not null. But somewhere during the picture taking process that value DOES become null. The 2nd check during onResult() returns false. Again, this is almost identical to my setup in the other activity, where it works fine.

Any thoughts?

JMRboosties
  • 15,500
  • 20
  • 76
  • 116

2 Answers2

68

Your activity gets destroyed during the Camera activity operation and re-created afterwards. You should use onSaveInstanceState/onRestoreInstanceState mechanism in your activity to preserve the image URI (and any other data) upon the activity restarts.

Like this:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (mImageUri != null) {
        outState.putString("cameraImageUri", mImageUri.toString());
    }
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState.containsKey("cameraImageUri")) {
        mImageUri = Uri.parse(savedInstanceState.getString("cameraImageUri"));
    }
}
Sergii Rudchenko
  • 5,170
  • 2
  • 28
  • 24
  • Ah... and the reason it DOES work in my other activity is because I overrode the destroy conditions in the manifest... Thanks! – JMRboosties Nov 23 '11 at 20:34
  • Also, the another activity may be lighter on resources and the Android OS doesn't kill it to give some air to the Camera app (which is heavy on resources itself). – Sergii Rudchenko Nov 23 '11 at 20:40
  • Had same issue.Thanks @SergiiRudchenko after adding onSaveInstanceState/onRestoreInstanceState it is working in samsung note 1. – Rohit Oct 09 '14 at 07:29
  • 1
    sometimes when given don't keep activities in developer options in the particular mobile this problem can happen too! – Learner_Programmer Apr 03 '15 at 08:04
  • To expand upon this, the Android OS can destroy your activity anytime if its not in the foreground if it needs additional memory. Therefore 'onSaveInstanceState' and 'onRestoreInstanceState' are great for telling the activity to save and then restore the fields that you activity might be using. As @Learner_Programmer mentioned, the low memory/destroying background activities, can be triggered by checking the "don't keep activities" in the developer options and is a great way to test your apps. – toidiu Aug 02 '16 at 02:25
3

I can suggest to create the initial (temporary) file at first, then pass the Uri in the Intent. In the function "onActivityResult()" you will have the file with the filled image.

File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "folderName");
dir.mkdirs();

if (dir.exists()) {
    try {
        imageFile = File.createTempFile("IMG_", ".jpg", dir);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

if (imageFile != null) {
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
    activity.startActivityForResult(cameraIntent, REQUEST_CODE);
} 
armansimonyan13
  • 956
  • 9
  • 15