diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt index e9d17f146..3746d3c3a 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt @@ -1,7 +1,6 @@ package io.legado.app.ui.config.otherConfig import android.Manifest -import android.content.Intent import android.os.Build import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult @@ -43,6 +42,7 @@ import io.legado.app.ui.widget.components.settingItem.InputSettingItem import io.legado.app.ui.widget.components.settingItem.SliderSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem import io.legado.app.utils.restart +import io.legado.app.utils.takePersistablePermissionSafely import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class) @@ -75,9 +75,7 @@ fun OtherConfigScreen( contract = ActivityResultContracts.OpenDocumentTree() ) { uri -> uri?.let { - val modeFlags = - Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - context.contentResolver.takePersistableUriPermission(it, modeFlags) + it.takePersistablePermissionSafely(context) viewModel.updateLocalBookDir(it.toString()) } } @@ -509,4 +507,4 @@ fun ConfirmDialog( } } ) -} \ No newline at end of file +} diff --git a/app/src/main/java/io/legado/app/ui/file/HandleFileActivity.kt b/app/src/main/java/io/legado/app/ui/file/HandleFileActivity.kt index 3f291866c..1fba0429d 100644 --- a/app/src/main/java/io/legado/app/ui/file/HandleFileActivity.kt +++ b/app/src/main/java/io/legado/app/ui/file/HandleFileActivity.kt @@ -23,6 +23,7 @@ import io.legado.app.utils.externalFiles import io.legado.app.utils.getJsonArray import io.legado.app.utils.isContentScheme import io.legado.app.utils.launch +import io.legado.app.utils.takePersistablePermissionSafely import io.legado.app.utils.toastOnUi import io.legado.app.utils.viewbindingdelegate.viewBinding import splitties.init.appCtx @@ -40,9 +41,7 @@ class HandleFileActivity : registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri -> uri?.let { if (uri.isContentScheme()) { - val modeFlags = - Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - contentResolver.takePersistableUriPermission(uri, modeFlags) + uri.takePersistablePermissionSafely(this) } onResult(Intent().setData(uri)) } ?: finish() @@ -51,9 +50,7 @@ class HandleFileActivity : private val selectDoc = registerForActivityResult(ActivityResultContracts.OpenDocument()) { it?.let { if (it.isContentScheme()) { - val modeFlags = - Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - contentResolver.takePersistableUriPermission(it, modeFlags) + it.takePersistablePermissionSafely(this) } onResult(Intent().setData(it)) } ?: finish() @@ -307,4 +304,4 @@ class HandleFileActivity : finish() } } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/legado/app/utils/UriExtensions.kt b/app/src/main/java/io/legado/app/utils/UriExtensions.kt index 17a760bf6..a90664b41 100644 --- a/app/src/main/java/io/legado/app/utils/UriExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/UriExtensions.kt @@ -29,6 +29,43 @@ fun Uri.isContentScheme() = this.scheme == "content" fun Uri.isFileScheme() = this.scheme == "file" +/** + * Some vendors return non-persistable content Uris even in system picker flows. + * Try to persist read/write grants separately and never throw. + */ +fun Uri.takePersistablePermissionSafely( + context: Context, + modeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION +): Boolean { + if (!isContentScheme()) return false + var granted = false + if (modeFlags and Intent.FLAG_GRANT_READ_URI_PERMISSION != 0) { + kotlin.runCatching { + context.contentResolver.takePersistableUriPermission( + this, + Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + }.onSuccess { + granted = true + }.onFailure { + AppLog.put("持久化读取权限失败: $this", it) + } + } + if (modeFlags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0) { + kotlin.runCatching { + context.contentResolver.takePersistableUriPermission( + this, + Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ) + }.onSuccess { + granted = true + }.onFailure { + AppLog.put("持久化写入权限失败: $this", it) + } + } + return granted +} + /** * 读取URI */