Merge pull request #656

Fix Xiaomi picker crash on non-persistable content Uri
This commit is contained in:
Kudomaga
2026-02-26 01:23:55 +08:00
committed by GitHub
4 changed files with 47 additions and 16 deletions
@@ -34,8 +34,7 @@ import java.io.InputStream
import java.net.MalformedURLException
import java.net.URL
import java.net.URLEncoder
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.concurrent.TimeUnit
import kotlin.coroutines.coroutineContext
@@ -219,8 +218,8 @@ open class WebDav(
val lastModify: Long = kotlin.runCatching {
element.findNS("getlastmodified", ns)
.firstOrNull()?.text()?.let {
LocalDateTime.parse(it, dateTimeFormatter)
.toInstant(ZoneOffset.of("+8")).toEpochMilli()
ZonedDateTime.parse(it, dateTimeFormatter)
.toInstant().toEpochMilli()
}
}.getOrNull() ?: 0
var fullURL = NetworkUtils.getAbsoluteURL(baseUrl, hrefDecode)
@@ -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(
}
}
)
}
}
@@ -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()
}
}
}
}
@@ -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
*/