5

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

Róbert Nagy
  • 6,720
  • 26
  • 45
James Black
  • 41,583
  • 10
  • 86
  • 166

3 Answers3

2

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.

LN-12
  • 792
  • 8
  • 19
  • 1
    It also worked for me! The reason is, for `singleInstance`, the system doesn't launch any other activities into the task holding the instance. So the activity doesn't receive the result. Instead, we can use `singleTask`. For details: https://stackoverflow.com/a/5118924/2263329 – Mahmudul Hasan Shohag Dec 14 '21 at 14:05
0

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)
James Black
  • 41,583
  • 10
  • 86
  • 166
  • I have similar setup as you did and also used a `FileProvider`. So you suggested that `FileProvider` didn't create the directories for you and you had to check & create folders beforehand? – dumbfingers Jan 21 '22 at 09:16
  • For the `GRAND_URI_PERMISSION` I think it's unnecessary because when adding `` tag into `AndroidManifest.xml`, you could add this:`android:grantUriPermissions="true"` to it – dumbfingers Jan 21 '22 at 09:18
0

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.

Róbert Nagy
  • 6,720
  • 26
  • 45