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
This commit is contained in:
Ken Swenson 2018-01-12 04:57:21 -05:00 committed by Bram van de Kerkhof
parent 634356e72f
commit b0482003bd
3 changed files with 62 additions and 37 deletions

View file

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.setting
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity import android.app.Activity
import android.app.Dialog import android.app.Dialog
import android.content.ActivityNotFoundException
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent 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.DialogController
import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
import eu.kanade.tachiyomi.util.getUriCompat import eu.kanade.tachiyomi.util.*
import eu.kanade.tachiyomi.util.registerLocalReceiver
import eu.kanade.tachiyomi.util.toast
import eu.kanade.tachiyomi.util.unregisterLocalReceiver
import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -116,19 +114,22 @@ class SettingsBackupController : SettingsController() {
onClick { onClick {
val currentDir = preferences.backupsDirectory().getOrDefault() val currentDir = preferences.backupsDirectory().getOrDefault()
try{
val intent = if (Build.VERSION.SDK_INT < 21) { val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// Custom dir selected, open directory selector // Custom dir selected, open directory selector
val i = Intent(activity, CustomLayoutPickerActivity::class.java) preferences.context.getFilePicker(currentDir)
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 { } else {
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
} }
startActivityForResult(intent, CODE_BACKUP_DIR) 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)
}
}
} }
preferences.backupsDirectory().asObservable() preferences.backupsDirectory().asObservable()
@ -204,17 +205,14 @@ class SettingsBackupController : SettingsController() {
fun createBackup(flags: Int) { fun createBackup(flags: Int) {
backupFlags = flags backupFlags = flags
// If API lower as KitKat use custom dir picker // Setup custom file picker intent
val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// Get dirs // Get dirs
val preferences: PreferencesHelper = Injekt.get()
val currentDir = preferences.backupsDirectory().getOrDefault() val currentDir = preferences.backupsDirectory().getOrDefault()
Intent(activity, CustomLayoutPickerActivity::class.java) try {
.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false) // If API is lower than Lollipop use custom picker
.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true) val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR) preferences.context.getFilePicker(currentDir)
.putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
} else { } else {
// Use Androids build in file creator // Use Androids build in file creator
Intent(Intent.ACTION_CREATE_DOCUMENT) Intent(Intent.ACTION_CREATE_DOCUMENT)
@ -222,7 +220,15 @@ class SettingsBackupController : SettingsController() {
.setType("application/*") .setType("application/*")
.putExtra(Intent.EXTRA_TITLE, Backup.getDefaultFilename()) .putExtra(Intent.EXTRA_TITLE, Backup.getDefaultFilename())
} }
startActivityForResult(intent, CODE_BACKUP_CREATE) 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)
}
}
} }
class CreateBackupDialog : DialogController() { class CreateBackupDialog : DialogController() {

View file

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.setting
import android.app.Activity import android.app.Activity
import android.app.Dialog import android.app.Dialog
import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build 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.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.DiskUtil import eu.kanade.tachiyomi.util.DiskUtil
import eu.kanade.tachiyomi.util.getFilePicker
import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -150,17 +152,19 @@ class SettingsDownloadController : SettingsController() {
} }
fun customDirectorySelected(currentDir: String) { 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 { } else {
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(i, DOWNLOAD_DIR_L) 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)
}
}
} }
} }

View file

@ -16,6 +16,8 @@ import android.support.v4.app.NotificationCompat
import android.support.v4.content.ContextCompat import android.support.v4.content.ContextCompat
import android.support.v4.content.LocalBroadcastManager import android.support.v4.content.LocalBroadcastManager
import android.widget.Toast import android.widget.Toast
import com.nononsenseapps.filepicker.FilePickerActivity
import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
/** /**
* Display a toast in this context. * Display a toast in this context.
@ -50,6 +52,19 @@ inline fun Context.notification(channelId: String, func: NotificationCompat.Buil
return builder.build() 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. * Checks if the give permission is granted.
* *