我必须使用 Retrofit MultiPart 发送图像。因此,我显示一个对话框以从图库或相机中进行选择。画廊作品。
在相机上我遇到问题,因为仅在请求许可后才能工作。例如,如果我接受了相机权限,那么我可以启动相机并获取 URI(当我执行
.exist
时,是 true
但内容长度为 0。
但是如果我显示权限对话框。只有这一次有效。
我的启动器:
val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
if (it && uri.path?.isNotEmpty() == true) {
viewmodel.onImageUpdated(uri)
}
}
创建 URI 和临时文件:
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
)
}
我的清单
<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>
和路径提供者
<?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>
现在,当用户选择相机时,我只需调用 -> (文件不起作用的情况):
val permissionCheckResult = ContextCompat.checkSelfPermission(
context, android.Manifest.permission.CAMERA
)
if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
cameraLauncher.launch(uri)
} else {
permissionLauncher.launch(android.Manifest.permission.CAMERA)
}
如果用户没有权限 -> 这有效:
val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) {
if (it) {
cameraLauncher.launch(uri)
} else {
Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
我真的不知道哪里出了问题,因为它的功能是一样的。
继续:
当我在接受相机权限后调用cameraLauncher 时,URI 包含图像。如果我接受了许可,则 URI 不包含图像。
最后感谢@blackapps,我找到了解决方案。
我认为问题在于重组。为了解决这个问题,我只需在我的 Uri 和文件中包含一个记住内容
val file = remember { context.createImageFile() }
val uri = remember {
FileProvider.getUriForFile(
Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + ".provider", file
)
}