我注意到以下异常(Firebase Crashlytics):
Fatal Exception: java.lang.RuntimeException
Failure delivering result ResultInfo{who=null, request=1915322883, result=-1, data=Intent { dat=content:/... flg=0xc3 }} to activity {com..../com....Activity}: java.lang.SecurityException: No persistable permission grants found for UID 10571 and Uri content:/...
Fatal Exception: java.lang.SecurityException
No persistable permission grants found for UID 10434 and Uri content:/...
android.content.ContentResolver.takePersistableUriPermission (ContentResolver.java:2952)
Caused by android.os.RemoteException
Remote stack trace: at com.android.server.uri.UriGrantsManagerService.takePersistableUriPermission(UriGrantsManagerService.java:385) at android.app.IUriGrantsManager$Stub.onTransact(IUriGrantsManager.java:139) at android.os.Binder.execTransactInternal(Binder.java:1375) at android.os.Binder.execTransact(Binder.java:1311)
当应用程序调用时ContentResolver.takePersistableUriPermission
:
val safResultLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { activityResult ->
coroutineScope.launch {
if (activityResult.resultCode == Activity.RESULT_OK) {
val treeUri = activityResult.data?.data
if (treeUri != null) {
context.contentResolver.takePersistableUriPermission(
treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
}
}
}
// select a folder
try {
safResultLauncher.launch(Intent.ACTION_OPEN_DOCUMENT_TREE)
} catch (e: Throwable) {
// ...
}
仅适用于三星设备(Android 13-14):
- 银河 S24 Ultra
- 银河S24+
- 银河 S21+ 5G
- 银河 S20 FE 5G
- Galaxy Z Fold5
- 银河 Z Flip4
- 银河 Z Flip4
- 银河A24
- 银河 A15 5G
- 银河A15
- 银河 A14 5G
更新
因此,我想由于限制,我们可能会尝试清除当前的持久 uri 授予(当您不需要它时),并在无法为某些存储获取持久 uri 时处理异常:
fun grantPermissionForFolderSaf(
context: Context,
activityResult: ActivityResult,
): Uri? {
if (activityResult.resultCode == Activity.RESULT_OK) {
val treeUri = activityResult.data?.data
if (treeUri != null) {
clearAllPersistedUriPermissions(context)
try {
context.contentResolver.takePersistableUriPermission(
/* uri = */ treeUri,
/* modeFlags = */ Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
return treeUri
} catch (e: Throwable) {
// ... explanation for a user to try to select a different storage
}
}
}
return null
}
private fun clearAllPersistedUriPermissions(context: Context) {
try {
val contentResolver = context.contentResolver
for (uriPermission in contentResolver.persistedUriPermissions) {
contentResolver.releasePersistableUriPermission(
/* uri = */ uriPermission.uri,
/* modeFlags = */ Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
} catch (e: Throwable) {
// just to be safe...
e.printStackTrace()
}
}
当您请求许可时,无法保证您会获得持久的许可。您的应用程序只能请求这么多(以前的限制是 128,但对于您的设备来说应该是 512)。此外,制造商或
DocumentsProvider
开发商可能不会为用户所做的某些选择提供持久权限。takePersistableUriPermission()
您需要优雅地处理引发异常的情况。