From 7a179368556c25f1c0c2ccd8891ca44f339b0387 Mon Sep 17 00:00:00 2001 From: birdbird <6892457-tzugen@users.noreply.gitlab.com> Date: Thu, 18 May 2023 10:32:17 +0000 Subject: [PATCH] Modernize Activity launching to set custom cache location --- .../ultrasonic/fragment/SettingsFragment.kt | 91 +++++-------------- .../util/SelectCacheActivityContract.kt | 49 ++++++++++ .../org/moire/ultrasonic/util/Settings.kt | 6 +- .../kotlin/org/moire/ultrasonic/util/Util.kt | 1 + 4 files changed, 76 insertions(+), 71 deletions(-) create mode 100644 ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/SelectCacheActivityContract.kt diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SettingsFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SettingsFragment.kt index 6245ce45..295885ea 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SettingsFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SettingsFragment.kt @@ -1,14 +1,11 @@ package org.moire.ultrasonic.fragment -import android.app.Activity import android.content.DialogInterface import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.net.Uri -import android.os.Build import android.os.Bundle -import android.provider.DocumentsContract import android.provider.SearchRecentSuggestions import android.view.View import androidx.annotation.StringRes @@ -38,6 +35,7 @@ import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.ErrorDialog import org.moire.ultrasonic.util.FileUtil.ultrasonicDirectory import org.moire.ultrasonic.util.InfoDialog +import org.moire.ultrasonic.util.SelectCacheActivityContract import org.moire.ultrasonic.util.Settings import org.moire.ultrasonic.util.Settings.id3TagsEnabledOnline import org.moire.ultrasonic.util.Settings.preferences @@ -100,64 +98,14 @@ class SettingsFragment : updateCustomPreferences() } - /** - * This function will be called when we return from the file picker - * with a new custom cache location - * - * TODO: This method has been deprecated in favor of using the Activity Result API - * which brings increased type safety via an ActivityResultContract and the prebuilt - * contracts for common intents available in - * androidx.activity.result.contract.ActivityResultContracts, - * provides hooks for testing, and allow receiving results in separate, - * testable classes independent from your fragment. - * Use registerForActivityResult(ActivityResultContract, ActivityResultCallback) with the - * appropriate ActivityResultContract and handling the result in the callback. - */ - override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { - if ( - requestCode == SELECT_CACHE_ACTIVITY && - resultCode == Activity.RESULT_OK && - resultData != null - ) { - val read = (resultData.flags and Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 - val write = (resultData.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 - val persist = (resultData.flags and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0 - - if (read && write && persist) { - if (resultData.data != null) { - // The result data contains a URI for the document or directory that - // the user selected. - val uri = resultData.data!! - val contentResolver = UApp.applicationContext().contentResolver - - contentResolver.takePersistableUriPermission(uri, RW_FLAG) - setCacheLocation(uri.toString()) - setupCacheLocationPreference() - return - } - } - ErrorDialog.Builder(requireContext()) - .setMessage(R.string.settings_cache_location_error) - .show() - } - - if (Settings.cacheLocationUri == "") { - Settings.customCacheLocation = false - customCacheLocation?.isChecked = false - setupCacheLocationPreference() - } - } - override fun onResume() { super.onResume() - val preferences = preferences preferences.registerOnSharedPreferenceChangeListener(this) } override fun onPause() { super.onPause() - val prefs = preferences - prefs.unregisterOnSharedPreferenceChangeListener(this) + preferences.unregisterOnSharedPreferenceChangeListener(this) } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { @@ -249,19 +197,31 @@ class SettingsFragment : } private fun selectCacheLocation() { - // Choose a directory using the system's file picker. - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - - if (Settings.cacheLocationUri != "" && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Settings.cacheLocationUri) - } - - intent.addFlags(RW_FLAG) - intent.addFlags(PERSISTABLE_FLAG) - - startActivityForResult(intent, SELECT_CACHE_ACTIVITY) + // Start the activity to pick a directory using the system's file picker. + selectCacheActivityContract.launch(Settings.cacheLocationUri) } + // Custom activity result contract + private val selectCacheActivityContract = + registerForActivityResult(SelectCacheActivityContract()) { uri -> + // parseResult will return the chosen path as an Uri + if (uri != null) { + val contentResolver = UApp.applicationContext().contentResolver + contentResolver.takePersistableUriPermission(uri, RW_FLAG) + setCacheLocation(uri.toString()) + setupCacheLocationPreference() + } else { + ErrorDialog.Builder(requireContext()) + .setMessage(R.string.settings_cache_location_error) + .show() + if (Settings.cacheLocationUri == "") { + Settings.customCacheLocation = false + customCacheLocation?.isChecked = false + setupCacheLocationPreference() + } + } + } + private fun setupBluetoothDevicePreferences() { val resumeSetting = Settings.resumeOnBluetoothDevice val pauseSetting = Settings.pauseOnBluetoothDevice @@ -425,7 +385,6 @@ class SettingsFragment : } companion object { - const val SELECT_CACHE_ACTIVITY = 161161 const val RW_FLAG = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION const val PERSISTABLE_FLAG = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/SelectCacheActivityContract.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/SelectCacheActivityContract.kt new file mode 100644 index 00000000..88437aca --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/SelectCacheActivityContract.kt @@ -0,0 +1,49 @@ +/* + * SelectCacheActivityContract.kt + * Copyright (C) 2009-2023 Ultrasonic developers + * + * Distributed under terms of the GNU GPLv3 license. + */ + +package org.moire.ultrasonic.util + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.provider.DocumentsContract +import androidx.activity.result.contract.ActivityResultContract +import org.moire.ultrasonic.fragment.SettingsFragment + +class SelectCacheActivityContract : ActivityResultContract() { + override fun createIntent(context: Context, input: String?): Intent { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + if (Settings.cacheLocationUri != "" && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, input) + } + intent.addFlags(SettingsFragment.RW_FLAG) + intent.addFlags(SettingsFragment.PERSISTABLE_FLAG) + return intent + } + + override fun parseResult(resultCode: Int, intent: Intent?): Uri? { + if ( + resultCode == Activity.RESULT_OK && + intent != null + ) { + val read = (intent.flags and Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + val write = (intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + val persist = (intent.flags and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0 + + if (read && write && persist) { + if (intent.data != null) { + // The result data contains a URI for the document or directory that + // the user selected. + return intent.data!! + } + } + } + return null + } +} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Settings.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Settings.kt index c8ebad0b..e1f421f0 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Settings.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Settings.kt @@ -48,7 +48,6 @@ object Settings { @JvmStatic val preloadCount: Int get() { - val preferences = preferences val preloadCount = preferences.getString(getKey(R.string.setting_key_preload_count), "-1")!! .toInt() @@ -60,7 +59,6 @@ object Settings { @JvmStatic val cacheSizeMB: Int get() { - val preferences = preferences val cacheSize = preferences.getString( getKey(R.string.setting_key_cache_size), "-1" @@ -209,7 +207,6 @@ object Settings { @JvmStatic val shareGreeting: String? get() { - val preferences = preferences val context = Util.appContext() val defaultVal = String.format( context.resources.getString(R.string.share_default_greeting), @@ -278,8 +275,7 @@ object Settings { } fun getAllKeys(): List { - val prefs = PreferenceManager.getDefaultSharedPreferences(UApp.applicationContext()) - return prefs.all.keys.toList() + return preferences.all.keys.toList() } private val appContext: Context diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Util.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Util.kt index 40739ee7..83ecb11b 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Util.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Util.kt @@ -833,6 +833,7 @@ object Util { Timber.d("Current user preferences") Timber.d("========================") val keys = Settings.preferences.all + keys.forEach { Timber.d("${it.key}: ${it.value}") }