浏览代码

Handle ActivityNotFoundException (#1170)

* [SettingsBackupController] Handle ActivityNotFoundException

When using `Intent.ACTION_CREATE_DOCUMENT` on SDK >= Lollipop there is no
guarantee that the ROM supports the built in file picker such as MIUI

* [SettingsBackupController] Add import for ActivityNotFoundException

* Add additional handlers to Android document intents

* Requested review changes

Move `try {`s to top of block
Replace version numbers with `Build.VERSION_CODES.LOLLIPOP`
Break out custom file picker intent to Context extention `Context.getFilePicker`
Rename `val i` to `val intent` to be more clear with variable names

* Add version check to custom file picker after exception
Ken Swenson 7 年之前
父节点
当前提交
b0482003bd

+ 36 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt

@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.setting
 import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
 import android.app.Activity
 import android.app.Dialog
+import android.content.ActivityNotFoundException
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
@@ -26,10 +27,7 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag
 import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
-import eu.kanade.tachiyomi.util.getUriCompat
-import eu.kanade.tachiyomi.util.registerLocalReceiver
-import eu.kanade.tachiyomi.util.toast
-import eu.kanade.tachiyomi.util.unregisterLocalReceiver
+import eu.kanade.tachiyomi.util.*
 import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
@@ -116,19 +114,22 @@ class SettingsBackupController : SettingsController() {
 
                 onClick {
                     val currentDir = preferences.backupsDirectory().getOrDefault()
-
-                    val intent = if (Build.VERSION.SDK_INT < 21) {
+                    try{
+                        val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                         // Custom dir selected, open directory selector
-                        val i = Intent(activity, CustomLayoutPickerActivity::class.java)
-                        i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
-                        i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
-                        i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR)
-                        i.putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
-
-                    } else {
-                        Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
+                        preferences.context.getFilePicker(currentDir)
+                        } else {
+                          Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
+                        }
+
+                        startActivityForResult(intent, CODE_BACKUP_DIR)
+                    } catch (e: ActivityNotFoundException){
+                        //Fall back to custom picker on error
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
+                            startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_DIR)
+                        }
                     }
-                    startActivityForResult(intent, CODE_BACKUP_DIR)
+
                 }
 
                 preferences.backupsDirectory().asObservable()
@@ -204,25 +205,30 @@ class SettingsBackupController : SettingsController() {
     fun createBackup(flags: Int) {
         backupFlags = flags
 
-        // If API lower as KitKat use custom dir picker
-        val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            // Get dirs
-            val preferences: PreferencesHelper = Injekt.get()
-            val currentDir = preferences.backupsDirectory().getOrDefault()
-
-            Intent(activity, CustomLayoutPickerActivity::class.java)
-                    .putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
-                    .putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
-                    .putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR)
-                    .putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
-        } else {
-            // Use Androids build in file creator
-            Intent(Intent.ACTION_CREATE_DOCUMENT)
+        // Setup custom file picker intent
+        // Get dirs
+        val currentDir = preferences.backupsDirectory().getOrDefault()
+
+        try {
+            // If API is lower than Lollipop use custom picker
+            val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                preferences.context.getFilePicker(currentDir)
+            } else {
+                // Use Androids build in file creator
+                Intent(Intent.ACTION_CREATE_DOCUMENT)
                     .addCategory(Intent.CATEGORY_OPENABLE)
                     .setType("application/*")
                     .putExtra(Intent.EXTRA_TITLE, Backup.getDefaultFilename())
+            }
+
+            startActivityForResult(intent, CODE_BACKUP_CREATE)
+        } catch (e: ActivityNotFoundException) {
+            // Handle errors where the android ROM doesn't support the built in picker
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
+                startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_CREATE)
+            }
         }
-        startActivityForResult(intent, CODE_BACKUP_CREATE)
+
     }
 
     class CreateBackupDialog : DialogController() {

+ 14 - 10
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt

@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.setting
 
 import android.app.Activity
 import android.app.Dialog
+import android.content.ActivityNotFoundException
 import android.content.Intent
 import android.net.Uri
 import android.os.Build
@@ -18,6 +19,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import eu.kanade.tachiyomi.util.DiskUtil
+import eu.kanade.tachiyomi.util.getFilePicker
 import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
@@ -150,17 +152,19 @@ class SettingsDownloadController : SettingsController() {
     }
 
     fun customDirectorySelected(currentDir: String) {
-        if (Build.VERSION.SDK_INT < 21) {
-            val i = Intent(activity, CustomLayoutPickerActivity::class.java)
-            i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
-            i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
-            i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR)
-            i.putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
-
-            startActivityForResult(i, DOWNLOAD_DIR_PRE_L)
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR_PRE_L)
         } else {
-            val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
-            startActivityForResult(i, DOWNLOAD_DIR_L)
+            val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
+            try {
+                startActivityForResult(intent, DOWNLOAD_DIR_L)
+            } catch (e: ActivityNotFoundException) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                    startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR_L)
+                }
+            }
+
         }
     }
 

+ 15 - 0
app/src/main/java/eu/kanade/tachiyomi/util/ContextExtensions.kt

@@ -16,6 +16,8 @@ import android.support.v4.app.NotificationCompat
 import android.support.v4.content.ContextCompat
 import android.support.v4.content.LocalBroadcastManager
 import android.widget.Toast
+import com.nononsenseapps.filepicker.FilePickerActivity
+import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
 
 /**
  * Display a toast in this context.
@@ -50,6 +52,19 @@ inline fun Context.notification(channelId: String, func: NotificationCompat.Buil
     return builder.build()
 }
 
+/**
+ * Helper method to construct an Intent to use a custom file picker.
+ * @param currentDir the path the file picker will open with.
+ * @return an Intent to start the file picker activity.
+ */
+fun Context.getFilePicker(currentDir: String): Intent {
+    return Intent(this, CustomLayoutPickerActivity::class.java)
+            .putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
+            .putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
+            .putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR)
+            .putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
+}
+
 /**
  * Checks if the give permission is granted.
  *