Search code examples
androidandroid-camera

How to get Image URI by intent MediaStore.ACTION_IMAGE_CAPTURE in Android 10 and above


FOR MODERATORS: I know there are already questions like this but all of those approaches endup giving bitmap through data.getExtra("data") which is actually just thumbnail. I want to get URI not bitmap and I need to get URI of ACTUAL IMAGE not its thumbnail with approach available in 2021. PLEASE CONSIDER THIS BEFORE TAGGING QUESTION AS DUPLICATE!

I am getting image from camera and its working fine on lower devices but its giving null in data when onActivityResult is called only in Android 10 and 11.

That's what I am doing

val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, ACTION_REQUEST_CAMERA)

Here is my onActivityResult

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == RESULT_OK && requestCode == ACTION_REQUEST_CAMERA) {

            data?.data?.let { uri ->
                 Toast.makeText(context, "Got URI", Toast.LENGTH_LONG).show()
            }
        }
    }

Solution

  • This approach worked for me

    In Manifest file

         <application>
            <provider
                android:name="androidx.core.content.FileProvider"
                android:authorities="com.example.android.provider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths">
                </meta-data>
            </provider>
         ...
         </application
    

    created a file /res/xml/file_paths.xml and specified path in that

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-files-path name="my_images" path="Pictures" />
    </paths>
    

    In my activity

    created a global variable var cameraPhotoFilePath: Uri? = null

    this is how I started Camera acitivity for results

    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                    val photoFile: File? = try {
                        createImageFileInAppDir()
                    } catch (ex: IOException) {
                        // Error occurred while creating the File
                        null
                    }
    
                    photoFile?.also { file ->
                        val photoURI: Uri = FileProvider.getUriForFile(
                            this,
                            "com.example.android.provider",
                            file
                        )
                        cameraPhotoFilePath = photoURI
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    }
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                    startActivityForResult(intent, ACTION_REQUEST_CAMERA)
    

    here is a helper function that i used in above code

    @Throws(IOException::class)
        private fun createImageFileInAppDir(): File {
            val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
            val imagePath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
            return   File(imagePath, "JPEG_${timeStamp}_" + ".jpg")
        }
    

    At the end in onActivityResult thats how I got image Uri

    if (resultCode == RESULT_OK && requestCode == ACTION_REQUEST_CAMERA) {
            cameraPhotoFilePath?.let { uri -> 
                // here uri is image Uri that was captured by camera
            }
        }