您的代码的问题是,您将empty Uri
传递给launch
,而相机应用程序无法保存这Uri
中的图像.如果打开TakePicture
类或将鼠标光标放在其上,您将看到以下信息:
一个ActivityResultContract来拍摄照片,并将其保存到
提供的内容-URI.如果图像保存到
给定的URI.
换句话说,TakePicture
类不会自动为您创建File
,您将不得不自己创建File
并提供Uri
.
我将假设一个简单的场景,即你想要在应用程序中为一些临时任务拍照.要实现此目标,您需要了解代码中缺少的一些步骤:
- 由于您需要创建
File
并将其公开给相机应用程序,因此您需要使用File Provider创建规则并在Manifest
文件中声明它.
- 创建
File
并将其Uri
与FileProvider
一起公开的函数.
让我们从file_paths.xml
开始(res/xml内部):
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path
name="cache_pictures"
path="/" />
</paths>
出于暂时保存文件的 idea ,我在这里使用了cache-path
.
在Manifest
文件中:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA" />
<application ...>
<activity .../>
<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/file_paths" />
</provider>
</application>
</manifest>
扩展以创建File
并返回Uri
:
fun Context.createTempPictureUri(
provider: String = "${BuildConfig.APPLICATION_ID}.provider",
fileName: String = "picture_${System.currentTimeMillis()}",
fileExtension: String = ".png"
): Uri {
val tempFile = File.createTempFile(
fileName, fileExtension, cacheDir
).apply {
createNewFile()
}
return FileProvider.getUriForFile(applicationContext, provider, tempFile)
}
在本例中,缓存文件夹使用的是cacheDir
.如果在这里改到filesDir
,一定要在cache-path
号公路上从file_paths.xml
改到files-path
.
现在,在Composable Screen
分钟内,你可以得到这样的东西:
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun SomeScreen() {
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 = context.createTempPictureUri()
cameraLauncher.launch(tempPhotoUri)
} 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")
}
}
}