Android Jetpack Compose中Picker URI权限异常问题求助
问题:重启应用后调用cleanupCheck触发SecurityException,无法访问相册Picker URI
我用Jetpack Compose开发了一款Android应用,通过Retrofit获取国家信息并存入MongoDB。用户进入国家详情页时可从相册选择图片关联至对应国家,首次安装应用时保存图片功能正常,但重启应用后会崩溃。
我通过URI将图片上传至Firebase,若上传中断会将会话信息保存至DAO,后续通过cleanupCheck方法重试上传/删除操作。但调用该方法时会触发如下致命异常:
FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.omersungur.theworldwander, PID: 13346 java.lang.SecurityException: Calling uid ( 10410 ) does not have permission to access picker uri: content://media/picker/0/com.android.providers.media.photopicker/media/1000005801 at android.os.Parcel.createExceptionOrNull(Parcel.java:3069) at android.os.Parcel.createException(Parcel.java:3053) at android.os.Parcel.readException(Parcel.java:3036) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190) at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:153) at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:814) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2043) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1858) at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1689) at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1635) at com.google.firebase.storage.UploadTask.(UploadTask.java:140) at com.google.firebase.storage.StorageReference.putFile(StorageReference.java:284) at com.omersungur.theworldwander.core.ExtFunctionKt.retryUploadingImageToFirebase(ExtFunction.kt:61) at com.omersungur.theworldwander.presentation.MainActivityKt$cleanupCheck$1.invokeSuspend(MainActivity.kt:108) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@b372588, Dispatchers.IO]
相关代码
相册选择器代码(Gallery Uploader Composable)
val context = LocalContext.current val multiplePhotoPicker = rememberLauncherForActivityResult( contract = ActivityResultContracts.PickMultipleVisualMedia(maxItems = 8), ) { images -> images.forEach { onImageSelect(it) val name = context.packageName context.grantUriPermission(name, it, Intent.FLAG_GRANT_READ_URI_PERMISSION) } }
MainActivity中的cleanupCheck方法
private fun cleanupCheck( scope: CoroutineScope, imageToUploadDao: ImageToUploadDao, imageToDeleteDao: ImageToDeleteDao ) { scope.launch(Dispatchers.IO) { val result = imageToUploadDao.getAllImages() result.forEach { imageToUpload -> retryUploadingImageToFirebase( imageToUpload = imageToUpload, onSuccess = { scope.launch(Dispatchers.IO) { imageToUploadDao.cleanupImage(imageToUpload.id) } } ) } val result2 = imageToDeleteDao.getAllImages() result2.forEach { imageToDelete -> retryDeletingImageFromFirebase( imageToDelete = imageToDelete, onSuccess = { scope.launch(Dispatchers.IO) { imageToDeleteDao.cleanupImage(imageId = imageToDelete.id) } } ) } } }
扩展函数
fun retryUploadingImageToFirebase( imageToUpload: ImageToUpload, onSuccess: () -> Unit ) { val storage = FirebaseStorage.getInstance().reference storage.child(imageToUpload.remoteImagePath).putFile( imageToUpload.imageUrl.toUri(), storageMetadata { }, imageToUpload.sessionUri.toUri() ).addOnSuccessListener { onSuccess() } } fun retryDeletingImageFromFirebase( imageToDelete: ImageToDelete, onSuccess: () -> Unit ) { val storage = FirebaseStorage.getInstance().reference storage.child(imageToDelete.remoteImagePath).delete() .addOnSuccessListener { onSuccess() } }
移除cleanupCheck调用后则无异常,项目地址:https://github.com/omersungur/TheWorldWander
内容的提问来源于stack exchange,提问作者omersungur
相关产品推荐
相关产品推荐

