How to get uri of captured photo?

16,390

Solution 1

Follow below steps.

Step - 1 : Create provider_paths.xml in res/xml folder and write below code in it.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="external_files"
        path="." />
</paths>

Step - 2 : Declare provider in manifest as below.

       <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

If you are facing error at: android:name="android.support.v4.content.FileProvider" Use:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

Step - 3 : Write your camera intent as below.

    Intent m_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File file = new File(Environment.getExternalStorageDirectory(), "MyPhoto.jpg");
    Uri uri = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);
    m_intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(m_intent, REQUEST_CAMERA_IMAGE);

Step - 4 : Handle camera result in onActivityResult as below.

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

        //TODO... onCamera Picker Result
        case REQUEST_CAMERA_IMAGE:
            if (resultCode == RESULT_OK) {

              //File object of camera image
                File file = new File(Environment.getExternalStorageDirectory(), "MyPhoto.jpg");

              //Uri of camera image
                Uri uri = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);

            }
            break;
    }
}

Solution 2

While calling Camera intent

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);


 File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "IMG_FOLDER");

        try {
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    return null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        imageURI = Uri.fromFile(new File(mediaStorageDir.getPath() + File.separator +
                "profile_img.jpg"));
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageURI);

        startActivityForResult(intent, Utils.CAMERA_REQUEST);

Inside onActivityResult

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        try {
            if (resultCode == RESULT_OK) {
                if (requestCode == Utils.CAMERA_REQUEST) {
                    if (imageURI != null) {             // use the same uri, that you initialized while calling camera intent
                     // do whatever you want to do with this Uri
                 }
                }
            }
         } catch(Exception E) {}  
  }

For Nougat, you need to add this below code in splash / launcher activity

if (Build.VERSION.SDK_INT >= 24) {
        try {
            Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
            m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

This will work in all version. I have tested it too.

Share:
16,390
neo
Author by

neo

Updated on June 09, 2022

Comments

  • neo
    neo almost 2 years

    What do I want to achieve? I want to get URI of the captured image and save it on Firebase. What did I try? First of all I needed to open the camera. Below how I did it:

     Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null)
            startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
    

    After capturing the image, I needed to get the URI of the image. Below how I did it:

    if (resultCode == Activity.RESULT_OK) {
            if (requestCode == CAMERA_REQUEST_CODE) {
                if (data != null) {
                    if (data.getData() != null) {
                       Uri capturedImageUri = data.getData(); 
                    } else {
                        Toast.makeText(getContext(), getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(getContext(), getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
                }
    

    So everything was OK. But only on some devices. I suppose that it works only on API level more than 21 devices. In other devices , getData() returns null.

    So, what I have done next? I found that I can get Bitmap of the image through following code:

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

    So, I have a bitmap of the image. And I needed to get the URI of this image. Below how I did it:

    public Uri getImageUri(Context inContext, Bitmap inImage) {
      String path = 
      Images.Media.insertImage(inContext.getContentResolver(), inImage, 
      "Title", null);
      return Uri.parse(path);
     } 
    

    Above code returns me URI, but the image has really bad quality.

    So, I kept looking for a solution. And found that the right way is to create the file when I start the CameraActivity and save the uri of that file. And onActivityResult I tried to get that uri. Below how I did it:

    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    
        if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
    
            }
            if (photoFile != null) {
                Uri photoUri = FileProvider.getUriForFile(getContext(), "i_dont_know_what_to_write_here", photoFile);
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
            }
    
        }
    

    And my onActivityResult became:

        if (resultCode == Activity.RESULT_OK) {
        if (requestCode == CAMERA_REQUEST_CODE) {
            if (data != null) {
     Uri capturedPhotoUri = 
     data.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
       } else {
       Toast.makeText(getContext(), 
       getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
                }
    

    The above concept requires to add some tags on manifest :

     <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="i_dont_know_what_to_write_here"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/my_paths" />
            </provider>
    

    My xml file is :

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
    <external-files-path name="images"/>
    </paths>
    

    The above method didn't work because data on onActivityReuslt was null.

    So, what I need to do in order to achieve my goal?