39

After searching a lot in all the related issues at Stack Overflow and finding nothing, please try to help me.

I created an intent for capture a picture. Then I saw different behavior at onActivityResult(): if I don't put any extra in the Intent (for small pics) the Intent in onActivityResult is ok, but when I put extras in the intent for writing the pic to a file, the intent in onActivityResult is null!

The Intent creation:

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// without the following line the intent is ok
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(takePictureIntent, actionCode);

Why is it null, and how can I solve it?

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
dvrm
  • 3,749
  • 4
  • 34
  • 43
  • Were you able to figure out how to utilize the Uri.fromFile(f) property once you are inside of OnActivityForResult()? – Coova Sep 23 '14 at 13:57

4 Answers4

67

It happens the same to me, if you are providing MediaStore.EXTRA_OUTPUT, then the intent is null, but you will have the photo in the file you provided (Uri.fromFile(f)).

If you don't specify MediaStore.EXTRA_OUTPUT then you will have an intent which contains the uri from the file where the camera has saved the photo.

Don't know if it as a bug, but it works that way.

EDIT: So in onActivityResult() you no longer need to check for data if null. The following worked with me:

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case PICK_IMAGE_REQUEST://actionCode
            if (resultCode == RESULT_OK && data != null && data.getData() != null) {
                //For Image Gallery
            }
            return;

        case CAPTURE_IMAGE_REQUEST://actionCode
            if (resultCode == RESULT_OK) {
                //For CAMERA
                //You can use image PATH that you already created its file by the intent that launched the CAMERA (MediaStore.EXTRA_OUTPUT)
                return;
            }
    }
}

Hope it helps

Amt87
  • 5,493
  • 4
  • 32
  • 52
richardtz
  • 4,993
  • 2
  • 27
  • 38
  • thanks for replying. how can i give the camera path to save the pics in another way? – dvrm Oct 09 '12 at 05:46
  • 3
    If you don't specify the EXTRA_OUPTUT you will have an Intent, which contains the uri of the picture, BUT it will be a thumbnail (not a full resolution one). Another way, probably will be to use the Camera API and create an instance of Camera, but I have no experience with this. – richardtz Oct 10 '12 at 09:45
  • 1
    One question for you : Why do you need an intent? I mean, you have the photo in the file, isn't it enough? It is not working as expected, as the intent is null, but at least you got the photo. – richardtz Oct 10 '12 at 09:49
  • cause i wanted to get the img with extras.get("data") to display it on the screen. it's easier way, no? – dvrm Oct 15 '12 at 10:07
  • 3
    Once you have the file, you can show it in many different ways, for instance, create a Bitmap with Bitmap.decodeFile (you can rescale here if needed), and set in an ImageView with ImageView.setImageBitmap. Another option could be to use ImageView.setImageUri and provide a Uri of the file. – richardtz Oct 16 '12 at 10:48
  • you are right, but i wanted shortcut.. anyway your comment is very useful for me and i'll use one of the ways you suggested. thanks for giving your time! – dvrm Oct 18 '12 at 05:45
  • how to tell if the user cancel the camera? – stackunderflow Jun 08 '15 at 07:25
  • 1
    Got you.. Thanks.. By the way, can you provide me the link to developer website which states that passing EXTRA_OUTPUT will return null intent in `onActivityResult()` ? – Chintan Soni Sep 30 '15 at 05:54
1

A sample written in Kotlin. You create a Uri for camera app, CameraFragment holds it until camera returns from saving your picture and gives it back to you in onActivityResult as you would expect.

CameraFragment.kt

Acts as an intermediary between consumer and camera app. Takes Uri as input and returns it in data Intent.

class CameraFragment : Fragment() {

    companion object {
        val TAG = CameraFragment::class.java.simpleName

        private val KEY_URI = ".URI"

        fun newInstance(uri: Uri, targetFragment: Fragment, requestCode: Int): CameraFragment {
            val args = Bundle()
            args.putParcelable(KEY_URI, uri)
            val fragment = CameraFragment()
            fragment.arguments = args
            fragment.setTargetFragment(targetFragment, requestCode)
            return fragment
        }
    }

    private lateinit var uri: Uri

    private var fired = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        retainInstance = true

        fired = savedInstanceState?.getBoolean("fired") ?: false

        if (!fired) {
            val args = arguments
            uri = args.getParcelable(KEY_URI)

            val i = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            i.putExtra(MediaStore.EXTRA_OUTPUT, uri)
            i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            context.grantUriPermission(i, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

            startActivityForResult(i, targetRequestCode)
            fired = true
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putBoolean("fired", fired)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == targetRequestCode) {
            context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

            val newData = Intent()
            newData.data = uri
            targetFragment.onActivityResult(requestCode, resultCode, newData)

            dismiss()
        }
    }

    private fun dismiss() {
        fragmentManager.beginTransaction().remove(this).commit()
    }
}

/** Grant Uri permissions for all camera apps. */
fun Context.grantUriPermission(intent: Intent, uri: Uri, modeFlags: Int) {
    val resolvedIntentActivities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    for (resolvedIntentInfo in resolvedIntentActivities) {
        val packageName = resolvedIntentInfo.activityInfo.packageName;
        grantUriPermission(packageName, uri, modeFlags);
    }
}

Invoke camera intent

this is a fragment in your app which will trigger the camera. RC_CAMERA is your request code for this action.

val uri = /* Your output Uri. */
val f = CameraFragment.newInstance(uri, this, RC_CAMERA)
fragmentManager.beginTransaction().add(f, CameraFragment.TAG).commit()

Handle camera result

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    when(requestCode) {
        RC_CAMERA -> {
            if (resultCode == Activity.RESULT_OK) {
                val uri = data?.data
                // Do whatever you need.
            }
        }
    }
}
Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
0

Where did you create the ffor the Uri.fromFile(f)?

It must be a valid File object. Try to create it before the EXTRA_OUTPUT line.

File f = new File("valid path");

Try with something like this:

File file = new File(dataFile);
Uri outFileUri = Uri.fromFile(file);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, outFileUri);
startActivityForResult(intent, TAKE_PHOTO);
JJD
  • 50,076
  • 60
  • 203
  • 339
Mun0n
  • 4,438
  • 4
  • 28
  • 46
  • i created this before. i'm quit sure that the file object is valid because the pictures are saved there ok. – dvrm Sep 24 '12 at 12:12
  • TAKE_PHOTO is 1888? in this way the onActivityResult() isn't invoked at all (to me..) is it invoked for you? i'm perplexed. – dvrm Oct 09 '12 at 08:03
  • TAKE_PHOTO is a private variable that you should define, to pass to the method who catchs the action – Mun0n Oct 09 '12 at 15:32
-7

use the following:

Bitmap bitmap = data.getExtras().getParcelable("data");

it works.

Jaden Gu
  • 9,143
  • 3
  • 23
  • 26