madone madone - 1 year ago 153
Android Question

Taking photo always returns RESULT_CANCELED (0) in onActivityResult(..)

I trying to build storage app using firebase storage sample app, and when I take a picture I always get RESUL_CANCELED in onActivityResult(..).
Here is the code:

private void launchCamera() {
Log.d(LOG_TAG, "launchCamera");

// Check that we have permission to read images from external storage.
String perm = Manifest.permission.WRITE_EXTERNAL_STORAGE;
if (!EasyPermissions.hasPermissions(this, perm)) {
EasyPermissions.requestPermissions(this, getString(R.string.rationale_storage),

// Choose file storage location, must be listed in res/xml/file_paths.xml
File externalDir = Environment.getExternalStorageDirectory();
File file = new File(externalDir, "photos/" + UUID.randomUUID().toString() + ".jpg");

// Create content:// URI for file, required since Android N
// See:
mFileUri = FileProvider.getUriForFile(this,
"", file);

// Create and launch the intent
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);

startActivityForResult(takePictureIntent, RC_TAKE_PICTURE);

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(LOG_TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
if (requestCode == RC_TAKE_PICTURE) {
if (resultCode == RESULT_OK) {
if (mFileUri != null) {
} else {
Log.w(LOG_TAG, "File URI is null");
} else {
Toast.makeText(this, "Taking picture failed.", Toast.LENGTH_SHORT).show();

logs: onActivityResult:101:0:Intent { }

Answer Source

So it depends from the version of the Android?

That depends on what you mean by that and what the bug is.

As I noted in my comment, ACTION_IMAGE_CAPTURE implementations have a history of bugs. There is a wide range of such bugs, not necessarily tied to Android OS version.

However, your code takes an interesting approach to EXTRA_OUTPUT: using FileProvider with a location on external storage. Long-term, FileProvider is a fine answer, as Android N is starting to ban file: Uri values. However, there are many camera apps that will have problems with content: Uri values, because the developers of those camera apps did not expect such values. For example, Google's own Camera app fails for ACTION_VIDEO_CAPTURE on content: Uri values, at least as of a couple of months ago, though it is fine for ACTION_IMAGE_CAPTURE.

Worse, there is no way for an app to advertise what schemes it supports for an extra. With the "data" facet of an Intent, the <intent-filter> can advertise supported schemes, but that does not work for extras. So, when you invoke ACTION_IMAGE_CAPTURE with a content: Uri in EXTRA_OUTPUT, you are not limited to camera apps that happen to support content: Uri values.

You might consider temporarily dropping your targetSdkVersion below 24, then using Uri.fromFile(file) instead of FileProvider.getUriForFile(...), and see what happens. If your original camera app works fine, then that app does not support content: Uri values correctly, and that was what caused your original problem.

Overall, I recommend that developers using ACTION_IMAGE_CAPTURE keep their targetSdkVersion below 24 and use file: Uri values for a few years, until such time as a higher percentage of users have a camera app installed that supports content: Uri values. Or, offer your users a choice between their existing camera apps (via ACTION_IMAGE_CAPTURE) and some camera capability that you build into your own app (e.g., using my library), to increase the odds that something will work.