6

I'm taking a picture like following:

activity.startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE), BaseDef.REQUEST_CODE_CAMERA);

Afterwards, I just want to get the new images path, uri or similar (NOT the bitmap or image data), so that I know where the new image is located. Therefore I try to retrieve the uri like following:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == BaseDef.REQUEST_CODE_CAMERA)
    {
        if (resultCode == RESULT_OK)
        {
            Uri uri = data.getData();
        }
    }
}

But the uri sometimes is null. How can I get the image path/uri on such devices?

EDIT

I really want to keep the default file name created by whichever camera app is used!

Current workaround (I don't know if this always works):

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == BaseDef.REQUEST_CODE_CAMERA)
    {
        if (resultCode == RESULT_OK)
        {
            String path = null;
            Uri uri = data.getData();
            if (uri != null)
                path = MediaUtil.getRealPathFromURI(uri);
            else
            {
                L.d(this, "URI == NULL => trying to get last image path directly");
                // here I just sort mediastore by id desc and get the first image's path
                // can I be sure this ALWAYS works? 
                // When the camera returns, the image SHOULD be already in the media store
                // If not, I would get a wrong image...
                path = MediaStoreUtil.getLastImagePath(); 
            }

            if (path == null)
            {
                L.d(this, "Path of camera image could not be retrieved");
                return;
            }
        }
    }
}
prom85
  • 16,896
  • 17
  • 122
  • 242

1 Answers1

1

NOTE: For targeting api-24 or higher, see here.

For targeting api-23 or lower:

The best way to do this is to send the Uri with the Intent used to open the camera. You will need to create a temp file that will be overwritten with the photo taken.

First, declare a member variable to store the Uri:

public class MyPhotoActivity extends AppCompatActivity {

    Uri uri;
    //.............

Setting up the temp file and passing the Uri to the camera app:

public void takePhoto() {
  counter++; //this is an int
  String imageFileName = "JPEG_" + counter; //make a better file name
  File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
  File image = File.createTempFile(imageFileName, 
                                   ".jpg", 
                                   storageDir
                                  );

  uri = Uri.fromFile(image);
  Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
  startActivityForResult(takePhotoIntent, BaseDef.REQUEST_CODE_CAMERA);
}

Then, if you get a success result in onActivityResult(), the temp file created has the captured image, and you can use uri for whatever you need:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == BaseDef.REQUEST_CODE_CAMERA)
    {
        if (resultCode == RESULT_OK)
        {
            //use uri member variable...
            //it has the image that was captured
        }
    }
}
Pei
  • 11,452
  • 5
  • 41
  • 45
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • 1
    I know this solution... I read, that creating a new media store entry beforehand and handing on this instead of a file is even more reliable... Still, this will results, that all images taken through my app may be stored in a differant location than if they would have taken directly through the camera... That's what a REALLY don't want by default. I want the image to be saved at the camera's default location – prom85 Nov 12 '15 at 08:00
  • @prom85 The best thing to do here is store them in the pictures directory in external storage using `Environment.DIRECTORY_PICTURES`. That way they are viewable in the gallery just like all other photos. – Daniel Nugent Nov 12 '15 at 08:04
  • 1
    It's not about viewability... I edited my first post and show my alternate solution... I want the image to be stored under `DCIM/Camera`, `DCIM/100Andro` or whatever directory the camera uses. I think a user of my app expects that if he takes the image with camera 1, the image is saved in the directory of camera 1, if it uses camera 2, the image should be saved in camera 2's directory. I don't want that opening the camera directly or through my app does effect the produced image's path (nor the name, but that would be acceptable)... – prom85 Nov 12 '15 at 08:10
  • starting android 24+, it will fail http://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed – DayDayHappy Apr 23 '17 at 14:37