2

I'm not able to retrieve the photo I have just captured. I believe its something wrong with my OnActivityResult, case CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE. Retrieving photo from album by case 1 works fine. Please kindy advice.

Source Code:

    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
        super.onActivityResult(requestCode, resultCode, data); 
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
           if(resultCode == RESULT_OK){     
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
           if(resultCode == RESULT_CANCELED){   
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
           else{  ; 
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
    }   
    else if(requestCode == 1) {
        if(resultCode == RESULT_OK){  
            Uri selectedImage = data.getData();
            imageView.setImageURI(selectedImage);
        }
    }
}

}

iceraven
  • 225
  • 1
  • 5
  • 16

3 Answers3

2

Whether or not you get the image is dependent on the manufacturer of the phone unfortunately. Every Android version and every Manufacturer seems to have a slightly different behavior. Sometimes the URL is provided in the result as "data" parameter (that's what you're doing), but sometimes it's just empty. I even got a phone once that returned RESULT_CANCEL although it worked perfectly.

As it seems there's no way around implementing all kind of different fallbacks. Here's my code I'm using currently in one of our projects. The member variable mTargetUri needs to be set to the output file name you provided as Intent parameter MediaStore.EXTRA_OUTPUT, mCaptureTime should be set to Sytem.currentTimeMillis() right before launching the Intent.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            Log.v(LOG_TAG, "Camera intent succeeded");
        }
        else if (resultCode == RESULT_CANCELED) {
            Log.i(LOG_TAG, "Camera intent aborted");
        }
        else {
            Log.e(LOG_TAG, "Camera intent failed with result code: " + resultCode);
        }

        // Regardless of the resultCode we're going to check if a new photo has been
        // created on the phone. At least on the Samsung Galaxy S3 the behavior
        // could be observed that although the result code was "0" the camera app
        // created two (!) files on the SD card.

        // Image captured and saved to fileUri specified in the Intent
        Uri targetUri = (data != null) ? data.getData() : null;
        if (targetUri == null) {
            Log.w(LOG_TAG, "Camera intent returned empty result.");
            targetUri = mTargetUri;
        }

        if (targetUri != null) {
            String targetFilePath = targetUri.getPath();
            File targetFile = new File(targetFilePath);
            if (targetFile.exists()) {
                Log.i(LOG_TAG, "Image saved to: " + targetUri.toString());

                // Fix for issue reported here: http://code.google.com/p/android/issues/detail?id=22822
                // and here: http://code.google.com/p/android/issues/detail?id=19268
                // We're following the proposed solution from https://stackoverflow.com/questions/8450539/
                int rotation = -1;
                long fileSize = targetFile.length();
                Cursor mediaCursor = getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                        new String[] { 
                            MediaStore.Images.ImageColumns.ORIENTATION, 
                            MediaStore.MediaColumns.SIZE,
                            MediaStore.MediaColumns.DATA }, 
                        MediaStore.MediaColumns.DATE_ADDED + ">=?", 
                        new String[] { String.valueOf(mCaptureTime/1000 - 1)}, 
                        MediaStore.MediaColumns.DATE_ADDED + " desc");

                if ((mediaCursor != null) && (mCaptureTime != 0)) {
                    if (mediaCursor.moveToFirst()) {
                        do {
                            long size = mediaCursor.getLong(1);
                            Uri uri = Uri.parse(mediaCursor.getString(2));
                            // Extra check to make sure that we are getting the orientation from the proper file
                            if (size == fileSize && !uri.equals(targetUri.toString())) {
                                rotation = mediaCursor.getInt(0);
                                break;
                            }
                        } while (mediaCursor.moveToNext());
                    }
                    mediaCursor.close();
                }

                if (rotation == -1) {
                    // It seems that there has been no duplication and no rotation issue so far. This means we can
                    // add our newly created file to the media library.
                    // TODO
                }
                else {
                    // Looks like the picture already exists in the media library. This indicates we got a duplicate.
                    Log.w(LOG_TAG, "Duplicate image found for " + targetUri.toString() + " in media library. Deleting the copy.");
                    if (!targetFile.delete()) {
                        Log.e(LOG_TAG, "Failed to delete duplicate image.");
                    }
                }
            }
            }
    }
}

The code originates from different sources here on Stackoverflow and other sites. The basic idea is that we

  1. disregard the result code (RESULT_OK or RESULT_CANCELED) as they are no indication whether a photo was taken and stored on the SD card or not. The code above just logs the value but continues in any case.
  2. Then we check if there was an URI provided by the intent result. If we get an URI then it's safe to assume that it will actually point to the newly taken photo. However, we won't get such an URI although everything succeeded perfectly. To handle that case we simply use the URI we've originally provided to the camera activity (mTargetUri) hoping that we'll find the new file there.
  3. On some newer devices the camera app automatically adds a new photo to the media library and then creates a second copy names in the way we originally specified in targetUri. The problem with this approach is that we end up with duplicate images. To address this we follow a logic that is derived from the following Stackoverflow question: Images taken with ACTION_IMAGE_CAPTURE always returns 1 for ExifInterface.TAG_ORIENTATION on some newer devices. I won't go into many details here (just follow the link to get a better understanding) but the basic idea is that we query the Android media store and check if it already contains our new photo by comparing timestamps (mCaptureTime is set to System.currentTimeMillis() when the capture intent was originally started).
  4. In case we have found an entry in the media store we simply delete the duplicate.

This logic should work in all cases with virtually any Android device out there. We have tested it on a dozen of different devices and Android versions without additional issues so far.

Community
  • 1
  • 1
André
  • 2,101
  • 20
  • 23
  • hi Andre, may i know whats the purpose of mCaptureTime and what is that set to? Also, do you mean i only have to change my onActvityResult's codes to the above? So in my case targetUri = fileUri? – iceraven Nov 10 '12 at 14:14
  • Also, for my case, its not the problem of resultcode since i added the same code to result ok and result canceled. I believe it did not enter the if statment for requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE. May i know why is this the reason? – iceraven Nov 10 '12 at 14:42
  • The basic logic about capture time and checking the rotation is derived from the following Stackoverflow response: http://stackoverflow.com/a/8864367/1510185. It also explains the idea behind it. In my tests I've always got the correct request code back from the called activity. So I expect this works as designed on all platforms. However, the result code and extras have differed greatly between devices. I'll update my answer to explain that in greater detail later. – André Nov 12 '12 at 15:57
  • instead of checking on `mCaptureTime` you can use safely rely on `MediaStore.Images.Media._ID` instead. Capture time has bugs on emulator. Credits to [@Emil Davtyan](http://stackoverflow.com/a/8555925/51966) – mente Dec 02 '13 at 15:54
2

I faced same problem , once check have you put any tag related to History ?

Do not put android:noHistory="true" tag in manifest

if you use android:noHistory="true" in your activity inside manifest , it will remove from stack after on stop .

Note : if you are using tab activity then also you should not use android:noHistory="true"

or else simply put android:noHistory="false" in activity inside manifest .

Partharaj Deb
  • 864
  • 1
  • 8
  • 22
sravan
  • 5,303
  • 1
  • 31
  • 33
0

Try taking turning your camera and taking the picture in Landscape Mode. It seems that Mediastore Camera Intent only takes Landscape photos.

birdman
  • 1,134
  • 13
  • 13