Calling ActivityResultContracts.TakePicture() false is returned so the image isn't being saved as expected

Viewed 1155

I am trying to save an image from the camera and it keeps returning false. I thought the image wasn't being displayed but when I looked at the filesystem I have lots of files but they are all of length zero.

Just some set up here.

val pictureResult = remember { mutableStateOf<Boolean?>(null)}
val context = LocalContext.current
val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
    pictureResult.value = it
    // $it is false
}

This will create the file that is in the screenshot.

fun createImageFile(extension:String): File {
    // Create an image file name
    val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    val imagePath: File = File(context.filesDir, directoryFromExtension(extension))
    return File(imagePath, "justme${timeStamp}${extension}"
    ).apply {
        myNewsCreatorViewModel.currentPhotoPath = absolutePath
    }
}

When the button is clicked I go through these steps, starting with the file returned from the previous method.

                val uri = FileProvider.getUriForFile(context, "com.mine.fileprovider", file)
                cameraLauncher.launch(uri)

This is the result after I set the pictureResult.value, the idea being to then show the image, or I currently show a text message if imageSaved was false that the file wasn't saved.

        pictureResult.value?.let { imageSaved ->
            run {
                // imageSaved is false
            }
        }

I can't tell what I am doing wrong, and I can't tell how to get more information as to why it failed to save the image properly.

Screenshot of file system showing files with length zero

3 Answers

In my case the issue was caused by the android:launchMode="singleInstance" setting in the app manifest. The contract returned false, but I could load the image from the given URI. After removing the setting, it started working.

It appears the solution is to add:

val storageDir: File? = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), directoryFromExtension(extension))
if(storageDir?.exists() == false && ".jpg" == extension) {
    storageDir.mkdirs()
}

And I am not certain if it helps but it works if I also put this before I call the intent.

context.grantUriPermission("com.mine.android", uri,
    Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

Do you have the following permissions declared in your AndroidManifest.xml?

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

IMO it's always a good idea to revisit Take photos from the official docs if you're bumping into unknown issues.

Related