Aris Guimerá
Aris Guimerá

Reputation: 1017

TakePicture Launcher only works first time after ask for permission on Jetpack Compose

I have to send a image with Retrofit MultiPart. So I show a dialog to select from gallery or Camera. Gallery works.

On camera I have a problem cause only works after ask for permission. For example if I have my camera permission accepted, then I can launch the camera and get the URI (when I do a .exist is true but the Content-Length is 0.

But if I show the permission dialog. ONLY this time works.

My launcher:

  val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
    if (it && uri.path?.isNotEmpty() == true) {
        viewmodel.onImageUpdated(uri)
    }
}

To create the URI and temp file:

val context = LocalContext.current
val file = context.createImageFile()
val uri = FileProvider.getUriForFile(
    Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + ".provider", file
)

fun Context.createImageFile(): File {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val imageFileName = "JPEG_" + timeStamp + "_"
return File.createTempFile(
    imageFileName, 
    ".jpg", 
    externalCacheDir
)

}

My Manifest

    <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/path_provider" />
    </provider>

And path provider

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

Now, when user select camera I just call -> (Case when file doesnt work):

    val permissionCheckResult = ContextCompat.checkSelfPermission(
                context, android.Manifest.permission.CAMERA
            )
            if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
                cameraLauncher.launch(uri)
            } else {
                permissionLauncher.launch(android.Manifest.permission.CAMERA)
            }

If user havent permission -> this works:

val permissionLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
) {
    if (it) {
        cameraLauncher.launch(uri)
    } else {
        Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
    }
}

I really don't know wha's wrong because its the same function.

RESUME:

When I call cameraLauncher after accept camera permission the URI contain the image. If I do with the permission accepted the URI doesnt contain the image.

Upvotes: 0

Views: 686

Answers (1)

Aris Guimer&#225;
Aris Guimer&#225;

Reputation: 1017

Finally and thank to @blackapps I found a solution.

I think the problem was the recomposition. To fix that I just include a remember on my Uri and File

val file = remember { context.createImageFile() }
val uri = remember {
    FileProvider.getUriForFile(
        Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + ".provider", file
    )
}

Upvotes: 0

Related Questions