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
@@ -24,7 +24,6 @@ import io.legado.app.data.entities.RuleSub
import io.legado.app.data.entities.SearchKeyword import io.legado.app.data.entities.SearchKeyword
import io.legado.app.data.entities.Server import io.legado.app.data.entities.Server
import io.legado.app.data.entities.TxtTocRule import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.AppWebDav
import io.legado.app.help.DirectLinkUpload import io.legado.app.help.DirectLinkUpload
import io.legado.app.help.LauncherIconHelp import io.legado.app.help.LauncherIconHelp
import io.legado.app.help.book.isLocal 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.ACache
import io.legado.app.utils.FileUtils import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.LogUtils
import io.legado.app.utils.compress.ZipUtils import io.legado.app.utils.compress.ZipUtils
import io.legado.app.utils.defaultSharedPreferences import io.legado.app.utils.defaultSharedPreferences
import io.legado.app.utils.fromJsonArray import io.legado.app.utils.fromJsonArray
@@ -59,7 +59,10 @@ import java.io.FileInputStream
*/ */
object Restore { object Restore {
private const val TAG = "Restore"
suspend fun restore(context: Context, uri: Uri) { suspend fun restore(context: Context, uri: Uri) {
LogUtils.d(TAG, "开始恢复备份 uri:$uri")
kotlin.runCatching { kotlin.runCatching {
FileUtils.delete(Backup.backupPath) FileUtils.delete(Backup.backupPath)
if (uri.isContentScheme()) { if (uri.isContentScheme()) {
@@ -212,7 +215,7 @@ object Restore {
AppLog.put("恢复阅读界面出错\n${it.localizedMessage}", it) AppLog.put("恢复阅读界面出错\n${it.localizedMessage}", it)
} }
} }
AppWebDav.downBgs() //AppWebDav.downBgs()
appCtx.getSharedPreferences(path, "config")?.all?.let { map -> appCtx.getSharedPreferences(path, "config")?.all?.let { map ->
val edit = appCtx.defaultSharedPreferences.edit() val edit = appCtx.defaultSharedPreferences.edit()
@@ -266,9 +269,14 @@ object Restore {
try { try {
val file = File(path, fileName) val file = File(path, fileName)
if (file.exists()) { if (file.exists()) {
LogUtils.d(TAG, "阅读恢复备份 $fileName 文件大小 ${file.length()}")
FileInputStream(file).use { 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) { } catch (e: Exception) {
AppLog.put("$fileName\n读取解析出错\n${e.localizedMessage}", e) AppLog.put("$fileName\n读取解析出错\n${e.localizedMessage}", e)
@@ -2,6 +2,7 @@ package io.legado.app.lib.permission
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@@ -11,9 +12,12 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.lifecycle.lifecycleScope
import io.legado.app.R import io.legado.app.R
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import io.legado.app.utils.registerForActivityResult
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.launch
class PermissionActivity : AppCompatActivity() { class PermissionActivity : AppCompatActivity() {
@@ -24,6 +28,10 @@ class PermissionActivity : AppCompatActivity() {
RequestPlugins.sRequestCallback?.onSettingActivityResult() RequestPlugins.sRequestCallback?.onSettingActivityResult()
finish() finish()
} }
private val settingActivityResultAwait =
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
private val requestPermissionResult =
registerForActivityResult(ActivityResultContracts.RequestPermission())
@SuppressLint("BatteryLife") @SuppressLint("BatteryLife")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -61,16 +69,23 @@ class PermissionActivity : AppCompatActivity() {
} }
Request.TYPE_REQUEST_NOTIFICATIONS -> showSettingDialog(permissions, rationale) { Request.TYPE_REQUEST_NOTIFICATIONS -> showSettingDialog(permissions, rationale) {
kotlin.runCatching { lifecycleScope.launch {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { kotlin.runCatching {
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
val intent = Intent() && requestPermissionResult.launch(Permissions.POST_NOTIFICATIONS)
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS ) {
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName) RequestPlugins.sRequestCallback?.onSettingActivityResult()
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid) finish()
settingActivityResult.launch(intent) } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
} else { //这种方案适用于 API 26, 即8.0(含8.0)以上可以用
openSettingsActivity() 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( Request.TYPE_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS -> showSettingDialog(
permissions, rationale permissions, rationale
) { ) {
kotlin.runCatching { lifecycleScope.launch {
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) kotlin.runCatching {
intent.setData(Uri.parse("package:$packageName")) val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.setClassName( intent.setData(Uri.parse("package:$packageName"))
"com.android.settings", val className =
"com.android.settings.fuelgauge.RequestIgnoreBatteryOptimizations" "com.android.settings.fuelgauge.RequestIgnoreBatteryOptimizations"
) val activities = packageManager.queryIntentActivities(
settingActivityResult.launch(intent) 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)
}
} }
} }
} }
@@ -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, *>
}