我正在使用 android studio、lenguage kotlin 来制作我的应用程序,我想在其中处理用户及其烹饪食谱。我需要使用用户想要分享的菜肴的图像。我正在努力保存图像。 现在我的代码是:
val context = LocalContext.current
val file = context.createImageFile()
val uri = FileProvider.getUriForFile(
Objects.requireNonNull(context),
context.packageName + ".provider", file
)
var capturedImageUri by remember {
mutableStateOf<Uri>(Uri.EMPTY)
}
val cameraLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
if (isSuccess) {
capturedImageUri = uri
}
}
val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) {
if (it) {
cameraLauncher.launch(uri)
} else {
Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
Button(
onClick = {
val permissionCheckResult = ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
)
if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
cameraLauncher.launch(uri)
} else {
permissionLauncher.launch(Manifest.permission.CAMERA)
}
},
contentPadding = ButtonDefaults.TextButtonContentPadding,
) {
Icon(
Icons.Filled.PhotoCamera,
contentDescription = "Camera icon",
modifier = Modifier.size(ButtonDefaults.IconSize)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text("Scatta foto")
}
if (capturedImageUri.path?.isNotEmpty() == true) {
AsyncImage(
model = ImageRequest.Builder(context)
.data(capturedImageUri)
.crossfade(true)
.build(),
contentDescription = "image taken"
)
photoURI = saveImage(context.applicationContext.contentResolver, capturedImageUri)
}
我也有这些功能:
fun saveImage(contentResolver: ContentResolver, capturedImageUri: Uri): String {
val bitmap = getBitmap(capturedImageUri, contentResolver)
val values = ContentValues()
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG_${SystemClock.uptimeMillis()}")
val imageUri =
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val outputStream = imageUri?.let { contentResolver.openOutputStream(it) }
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
outputStream?.close()
return imageUri.toString()
}
fun Context.createImageFile(): File {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val imageFileName = "JPEG_" + timeStamp + "_"
return File.createTempFile(
imageFileName,
".jpg",
externalCacheDir
)
}
private fun getBitmap(selectedPhotoUri: Uri, contentResolver: ContentResolver): Bitmap {
val bitmap = when {
Build.VERSION.SDK_INT < 28 -> MediaStore.Images.Media.getBitmap(
contentResolver,
selectedPhotoUri
)
else -> {
val source = ImageDecoder.createSource(contentResolver, selectedPhotoUri)
ImageDecoder.decodeBitmap(source)
}
}
return bitmap
}
问题是,当我尝试使用
photoURI = saveImage(context.applicationContext.contentResolver, capturedImageUri)
保存图像时,应用程序停止(“MyApp 已停止”)。有人可以帮助我吗?
suspend fun saveImage(contentResolver: ContentResolver, capturedImageUri: Uri): String =
withContext(Dispatchers.IO) {
val bitmap = getBitmap(capturedImageUri, contentResolver)
val values = ContentValues()
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG_${SystemClock.uptimeMillis()}")
val imageUri =
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val outputStream = imageUri?.let { contentResolver.openOutputStream(it) }
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
outputStream?.close()
return@withContext imageUri.toString()
}
此外,
saveImage
必须在协程范围内调用。举个例子:
viewModelScope.launch {
photoURI = saveImage(context.applicationContext.contentResolver, capturedImageUri)
}
此外,请验证您的 AndroidManifest.xml 文件中是否列出了以下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
从 Android 10(API 级别 29)开始,不推荐使用
MediaStore.Images.Media.insertImage
,您应该改用 ContentValues,就像在代码中一样。