0

I have a piece of code that's part of an Android app built using Jetpack Compose. This specific code snippet is within a function called ImagePicker(). The purpose of this function is to allow users to take photos using the device's camera and display the captured image on the screen. However, I'm encountering a problem after taking a photo and clicking "OK" on the camera's interface.

The code uses Jetpack Compose's composable functions, which are components that define the UI of the app. It also utilizes the Permissions API for requesting camera permissions and the ActivityResultContracts.TakePicture() contract to launch the camera app and capture images.

Inside the function, I've defined variables to hold URIs (Uniform Resource Identifiers) for the current and temporary photos. The currentPhotoUri should eventually hold the URI of the image that the user has just taken, and the tempPhotoUri is used to hold the temporary URI while the user is interacting with the camera app.

I've set up a callback using rememberLauncherForActivityResult to handle the result of the camera action. Once the user captures an image and confirms it by clicking "OK" on the camera interface, the callback should be triggered with a success parameter. If success is true, the code updates the currentPhotoUri with the value of tempPhotoUri, thus making the captured image visible on the screen.

To manage camera permissions, I'm using rememberPermissionState to check for and request the necessary permissions. If the permission is granted, the code creates a temporary image URI, launches the camera app using the tempPhotoUri, and awaits the user's photo capture.

The UI is composed of a column layout that centers its content both vertically and horizontally on the screen. Inside this layout, there's an AnimatedVisibility component that's intended to display the captured image when its URI is not empty. The image is loaded using the Coil library's AsyncImage composable, specifying the currentPhotoUri as the image model.

Additionally, there's a button labeled "Take a photo with Camera." Clicking this button is supposed to trigger the camera permission request and initiate the process of taking a photo.

However, despite following this logic, when I take a photo, confirm it, and click "OK" on the camera interface, the captured photo doesn't appear on the screen. Furthermore, it seems that the code to determine whether the operation was successful or not is not being executed. I'm seeking assistance to identify what might be causing this issue and how to ensure that the captured image is displayed as intended.

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ImagePicker() {
    val context = LocalContext.current
    var currentPhotoUri by remember { mutableStateOf(value = Uri.EMPTY) }
    var tempPhotoUri by remember { mutableStateOf(value = Uri.EMPTY) }

    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.TakePicture(),
        onResult = { success ->
            if (success) currentPhotoUri = tempPhotoUri
        }
    )

    val cameraPermissionState = rememberPermissionState(
        permission = Manifest.permission.CAMERA,
        onPermissionResult = { granted ->
            if (granted) {
                tempPhotoUri = createTempImageUri(context)
                cameraLauncher.launch(tempPhotoUri)
            } else print("camera permission is denied")
        }
    )

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Timber.d("Current: ${currentPhotoUri.toString()}")
        AnimatedVisibility(visible = currentPhotoUri.toString().isNotEmpty()) {
            // from coil library
            AsyncImage(
                modifier = Modifier.size(size = 240.dp),
                model = currentPhotoUri,
                contentDescription = null
            )
        }

        Button(onClick = cameraPermissionState::launchPermissionRequest) {
            Text(text = "Take a photo with Camera")
        }
    }
}
DoctorWho
  • 1,044
  • 11
  • 34

1 Answers1

1

I could not determine your createTempImageUri function so I made some small changes in your code and it is working now.

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ImagePicker() {
    val context = LocalContext.current
    var currentPhotoUri by remember { mutableStateOf(value = Uri.EMPTY) }
    //var tempPhotoUri by remember { mutableStateOf(value = Uri.EMPTY) }
    val file = context.createImageFile()
    val uri = FileProvider.getUriForFile(
        Objects.requireNonNull(context),
        BuildConfig.APPLICATION_ID + ".provider", file
    )

    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.TakePicture(),
        onResult = { success ->
            if (success) currentPhotoUri = uri
        }
    )

    val cameraPermissionState = rememberPermissionState(
        permission = Manifest.permission.CAMERA,
        onPermissionResult = { granted ->
            if (granted) {
                cameraLauncher.launch(uri)
            } else print("camera permission is denied")
        }
    )

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        AnimatedVisibility(visible = currentPhotoUri.toString().isNotEmpty()) {
            // from coil library
            AsyncImage(
                modifier = Modifier.size(size = 240.dp),
                model = currentPhotoUri,
                contentDescription = null
            )
        }
        Button(onClick = cameraPermissionState::launchPermissionRequest) {
            Text(text = "Take a photo with Camera")
        }
    }
}

fun Context.createImageFile(): File {
    // Create an image file name
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    val imageFileName = "JPEG_" + timeStamp + "_"
    return File.createTempFile(
        imageFileName, /* prefix */
        ".jpg", /* suffix */
        externalCacheDir /* directory */
    )
}

Also don't forget to add this configuration. Hopefully it benefits your business.

Screenshot: Result

EsatGozcu
  • 185
  • 8