Horis пре 2 година
родитељ
комит
d0d81299c6

+ 11 - 3
app/src/main/java/io/legado/app/help/storage/Restore.kt

@@ -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)

+ 48 - 18
app/src/main/java/io/legado/app/lib/permission/PermissionActivity.kt

@@ -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)
+                    }
                 }
             }
         }

+ 45 - 0
app/src/main/java/io/legado/app/utils/ActivityResult.kt

@@ -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, *>
+
+}