This commit is contained in:
Horis
2024-08-18 16:02:27 +08:00
parent 9b93baa122
commit 589a54da7d
3 changed files with 104 additions and 21 deletions

View File

@@ -24,7 +24,6 @@ import io.legado.app.data.entities.RuleSub
import io.legado.app.data.entities.SearchKeyword
import io.legado.app.data.entities.Server
import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.AppWebDav
import io.legado.app.help.DirectLinkUpload
import io.legado.app.help.LauncherIconHelp
import io.legado.app.help.book.isLocal
@@ -36,6 +35,7 @@ import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.ACache
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.LogUtils
import io.legado.app.utils.compress.ZipUtils
import io.legado.app.utils.defaultSharedPreferences
import io.legado.app.utils.fromJsonArray
@@ -59,7 +59,10 @@ import java.io.FileInputStream
*/
object Restore {
private const val TAG = "Restore"
suspend fun restore(context: Context, uri: Uri) {
LogUtils.d(TAG, "开始恢复备份 uri:$uri")
kotlin.runCatching {
FileUtils.delete(Backup.backupPath)
if (uri.isContentScheme()) {
@@ -212,7 +215,7 @@ object Restore {
AppLog.put("恢复阅读界面出错\n${it.localizedMessage}", it)
}
}
AppWebDav.downBgs()
//AppWebDav.downBgs()
appCtx.getSharedPreferences(path, "config")?.all?.let { map ->
val edit = appCtx.defaultSharedPreferences.edit()
@@ -266,9 +269,14 @@ object Restore {
try {
val file = File(path, fileName)
if (file.exists()) {
LogUtils.d(TAG, "阅读恢复备份 $fileName 文件大小 ${file.length()}")
FileInputStream(file).use {
return GSON.fromJsonArray<T>(it).getOrThrow()
return GSON.fromJsonArray<T>(it).getOrThrow().also { list ->
LogUtils.d(TAG, "阅读恢复备份 $fileName 列表大小 ${list.size}")
}
}
} else {
LogUtils.d(TAG, "阅读恢复备份 $fileName 文件不存在")
}
} catch (e: Exception) {
AppLog.put("$fileName\n读取解析出错\n${e.localizedMessage}", e)

View File

@@ -2,6 +2,7 @@ package io.legado.app.lib.permission
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -11,9 +12,12 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.lifecycle.lifecycleScope
import io.legado.app.R
import io.legado.app.exception.NoStackTraceException
import io.legado.app.utils.registerForActivityResult
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.launch
class PermissionActivity : AppCompatActivity() {
@@ -24,6 +28,10 @@ class PermissionActivity : AppCompatActivity() {
RequestPlugins.sRequestCallback?.onSettingActivityResult()
finish()
}
private val settingActivityResultAwait =
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
private val requestPermissionResult =
registerForActivityResult(ActivityResultContracts.RequestPermission())
@SuppressLint("BatteryLife")
override fun onCreate(savedInstanceState: Bundle?) {
@@ -61,16 +69,23 @@ class PermissionActivity : AppCompatActivity() {
}
Request.TYPE_REQUEST_NOTIFICATIONS -> showSettingDialog(permissions, rationale) {
kotlin.runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//这种方案适用于 API 26, 即8.0含8.0)以上可以用
val intent = Intent()
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)
settingActivityResult.launch(intent)
} else {
openSettingsActivity()
lifecycleScope.launch {
kotlin.runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& requestPermissionResult.launch(Permissions.POST_NOTIFICATIONS)
) {
RequestPlugins.sRequestCallback?.onSettingActivityResult()
finish()
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//这种方案适用于 API 26, 即8.0含8.0)以上可以用
val intent = Intent()
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)
settingActivityResult.launch(intent)
} else {
openSettingsActivity()
}
}
}
}
@@ -78,14 +93,29 @@ class PermissionActivity : AppCompatActivity() {
Request.TYPE_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS -> showSettingDialog(
permissions, rationale
) {
kotlin.runCatching {
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.setData(Uri.parse("package:$packageName"))
intent.setClassName(
"com.android.settings",
"com.android.settings.fuelgauge.RequestIgnoreBatteryOptimizations"
)
settingActivityResult.launch(intent)
lifecycleScope.launch {
kotlin.runCatching {
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.setData(Uri.parse("package:$packageName"))
val className =
"com.android.settings.fuelgauge.RequestIgnoreBatteryOptimizations"
val activities = packageManager.queryIntentActivities(
intent,
PackageManager.MATCH_DEFAULT_ONLY
)
if (activities.indexOfFirst { it.activityInfo.name == className } > -1) {
val component = intent.resolveActivity(packageManager)
if (component.className != className) {
intent.setClassName(
"com.android.settings",
className
)
settingActivityResultAwait.launch(intent)
}
}
intent.component = null
settingActivityResult.launch(intent)
}
}
}
}

View File

@@ -0,0 +1,45 @@
package io.legado.app.utils
import androidx.activity.result.contract.ActivityResultContract
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityOptionsCompat
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
fun <I, O> AppCompatActivity.registerForActivityResult(contract: ActivityResultContract<I, O>): ActivityResultLauncherAwait<I, O> {
var cout: CancellableContinuation<O>? = null
val launcher = registerForActivityResult(contract) {
cout?.resume(it)
}
return object : ActivityResultLauncherAwait<I, O>() {
override suspend fun launch(input: I, options: ActivityOptionsCompat?): O {
return suspendCancellableCoroutine {
cout = it
launcher.launch(input, options)
}
}
override fun unregister() {
launcher.unregister()
}
override fun getContract(): ActivityResultContract<I, *> {
return launcher.contract
}
}
}
abstract class ActivityResultLauncherAwait<I, O> {
suspend fun launch(input: I): O {
return launch(input, null)
}
abstract suspend fun launch(input: I, options: ActivityOptionsCompat?): O
abstract fun unregister()
abstract fun getContract(): ActivityResultContract<I, *>
}