You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中ActivityResultContracts.TakePicture始终返回false求助

问题根源

你传入cameraLauncher.launch()的是Uri.EMPTY,ActivityResultContracts.TakePicture要求必须传入可被相机应用写入的有效Uri,空Uri会导致拍照后无法保存照片,最终回调返回false。

解决步骤

1. 配置FileProvider(Android 7.0+必做)

因为Android 7.0及以上禁止直接使用file://格式的Uri,必须通过FileProvider生成安全的内容Uri:

  • 在AndroidManifest.xml的<application>标签内注册FileProvider:
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  • 在res/xml目录下创建file_paths.xml文件,定义相机可访问的文件目录:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 指向应用外部私有存储的Pictures目录 -->
    <external-files-path name="camera_photos" path="Pictures" />
</paths>

2. 修改Composable代码,生成有效Uri

替换原来的空Uri初始化,动态生成可写入的图片Uri:

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun SomeScreen(context: Context = LocalContext.current) {
    // 生成用于保存照片的有效Uri,用remember避免重组时重复创建
    val photoUri by remember {
        mutableStateOf(createCameraPhotoUri(context))
    }

    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.TakePicture(),
        onResult = { success ->
            if (success) {
                println("success")
                println("photo uri: $photoUri")
            } else println("result failed")
        }
    )

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

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = cameraPermissionState::launchPermissionRequest) {
            Text(text = "Take a photo with Camera")
        }
    }
}

// 生成相机拍照用的Uri工具方法
private fun createCameraPhotoUri(context: Context): Uri {
    val imageFileName = "PHOTO_${System.currentTimeMillis()}.jpg"
    // 应用私有外部存储目录,无需额外存储权限(Android 10+)
    val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    val imageFile = File(storageDir, imageFileName)
    return FileProvider.getUriForFile(
        context,
        "${context.packageName}.fileprovider", // 与Manifest中authorities一致
        imageFile
    )
}

3. 额外注意事项

  • 若目标设备是Android 9及以下,还需要在AndroidManifest.xml中添加WRITE_EXTERNAL_STORAGE权限,并在代码中动态请求该权限;
  • 确保file_paths.xml的路径配置正确,上述示例使用的是应用私有外部存储,不会涉及公共存储的权限问题。

内容的提问来源于stack exchange,提问作者Assis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:50:28