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
  • 54,176
  • 9
  • 103
  • 290
dvrm
  • 3,721
  • 4
  • 33
  • 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

5 Answers5

65

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,305
  • 4
  • 31
  • 51
richardtz
  • 4,955
  • 2
  • 25
  • 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? – stack underflow Jun 08 '15 at 07:25
  • 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
  • 36,392
  • 7
  • 100
  • 120
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
  • 47,369
  • 53
  • 194
  • 328
Mun0n
  • 4,397
  • 4
  • 26
  • 45
  • 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
0

When we will capture the image from Camera in android then Uri or data.getdata() comes null. we have two solutions to resolve this issue.

  1. We can got the Uri path from the Bitmap Image
  2. We can got the Uri path from cursor.

I will implement all methods here, Please carefully watch and read these:-

First i will tell how to get Uri from Bitmap Image: Complete code is :

First we will capture image through Intent that will same for both methods so this code i will write one time only here :

 // Capture Image


  captureImg.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (intent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(intent, reqcode);
            }

        }
    });

Now we will Implement OnActivityResult :-(This will be same for both above 2 methods):-

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


            if(requestCode==reqcode && resultCode==RESULT_OK)
            {

    Bitmap photo = (Bitmap) data.getExtras().get("data");
    ImageView.setImageBitmap(photo);

                // CALL THIS METHOD TO GET THE URI FROM THE BITMAP
                Uri tempUri = getImageUri(getApplicationContext(), photo);

                \\ Show Uri path based on Image
                Toast.makeText(LiveImage.this,"Here "+ tempUri, Toast.LENGTH_LONG).show();

               \\ Show Uri path based on Cursor Content Resolver
                Toast.makeText(this, "Real path for URI : "+getRealPathFromURI(tempUri), Toast.LENGTH_SHORT).show();
    }
            else
            {
                Toast.makeText(this, "Failed To Capture Image", Toast.LENGTH_SHORT).show();
            }
        }

\now we will create all above method to create Uri from Image and Cursor methods via classes:

Now URI path from Bitmap Image

 private Uri getImageUri(Context applicationContext, Bitmap photo) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        String path = MediaStore.Images.Media.insertImage(LiveImage.this.getContentResolver(), photo, "Title", null);
        return Uri.parse(path);
    }

\ Uri from Real path of saved image

  public String getRealPathFromURI(Uri uri) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        return cursor.getString(idx);
    }
Pradeep Kumar
  • 1,785
  • 1
  • 9
  • 19
-7

use the following:

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

it works.

Jaden Gu
  • 8,763
  • 3
  • 22
  • 25