[英]ActivityResultContracts.TakePicture - Image is not saved after activity orientation change
我正在使用活动结果 API(使用 FileProvider)将图像从相机保存到应用程序缓存文件夹,然后将其 URI 传递给另一个活动。
如果活动方向在操作过程中没有改变,它就会起作用。
但是当用户旋转 Camera 活动(由 ActivityResultContracts.TakePicture 合约启动)时 - 图像将不会被保存(创建的文件为 0 字节)。 在传递 URI 的活动中解码图像时出现错误:
android.graphics.ImageDecoder$DecodeException: Failed to create image decoder with message 'unimplemented'Input contained an error.
我试图以明显的方式解决问题 - 在相机回调启动之前以编程方式锁定方向并在之后解锁,但这只在第一次有效(可能听起来很奇怪,但就是这样),当方向再次改变时 - 问题仍然存在。 看起来在更改方向后,当前活动结果回调与 Camera 活动之间的连接断开了。 经过研究,事实证明,如果我不启动打开图像的活动 - 图像会正确保存。 我试图在另一个线程中延迟启动活动 - 但没有成功。
我仍然找不到方向改变时图像无法保存的原因。
主要活动:
class MainActivity : AppCompatActivity() {
private val tmpImageUri by lazy { FileUtils.getTmpFileUri(applicationContext) }
private val takeImageResult = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
if (isSuccess) {
// We have successfully (actually no) saved the image and can work with it via tmpImageUri
launchEditActivity(tmpImageUri)
}
}
private fun takePictureFromCamera() {
takeImageResult.launch(tmpImageUri)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.button.setOnClickListener {
takePictureFromCamera()
}
}
private fun launchEditActivity(uri: Uri){
val intent = Intent(this, EditActivity::class.java).apply {
data = uri
}
startActivity(intent)
}
}
我通过 URI 的活动:
class EditActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadImage()
}
private fun loadImage(){
intent.data?.let { uri ->
model.viewModelScope.launch(Dispatchers.IO) {
val bitmap = FileUtils.loadBitmapFromUri(applicationContext, uri)
runOnUiThread {
model.setImage(bitmap)
}
}
}
}
}
文件实用程序:
fun getTmpFileUri(context: Context): Uri {
clearCache(context)
val tmpFile = File.createTempFile("tmp", ".jpg", context.cacheDir)
return FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}
private fun clearCache(context: Context){
context.cacheDir.deleteRecursively()
}
fun loadBitmapFromUri(context: Context, uri: Uri): Bitmap{
val bitmap: Bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val src = ImageDecoder.createSource(context.contentResolver, uri)
ImageDecoder.decodeBitmap(src) { decoder, info, source ->
decoder.isMutableRequired = true
}
} else {
MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
}
return bitmap
}
问题出在tmpImageUri
变量中,该变量在方向更改时被重置。 在savedInstance
中保存并恢复它之后,一切都开始正常工作。 感谢@Selvin 的帮助。
固定主要活动:
class MainActivity : AppCompatActivity() {
companion object {
private const val KEY_TMP_FILE_URI = "tmpFileUri"
}
private var tmpImageUri: Uri? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
tmpImageUri =
if(savedInstanceState?.containsKey(KEY_TMP_FILE_URI) == true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
savedInstanceState.getParcelable(KEY_TMP_FILE_URI, Uri::class.java)
else savedInstanceState.getParcelable(KEY_TMP_FILE_URI)
else FileUtils.getTmpFileUri(applicationContext)
...
}
private val takeImageResult = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
if (isSuccess) {
tmpImageUri?.let { launchEditActivity(it) }
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(KEY_TMP_FILE_URI, tmpImageUri)
}
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.