From 68489ca37defbc5f52ee45f8080794edc4247fc3 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 14 Sep 2020 17:14:00 -0300 Subject: [PATCH] Fix compile warnings on AOSP 11 --- .../seedvault/UsbIntentReceiver.kt | 4 +- .../seedvault/plugins/saf/DocumentsStorage.kt | 5 +- .../restore/InstallProgressFragment.kt | 17 +++--- .../seedvault/restore/RestoreActivity.kt | 2 +- .../restore/RestoreProgressFragment.kt | 10 ++-- .../seedvault/restore/RestoreSetFragment.kt | 15 ++++-- .../seedvault/settings/AppStatusFragment.kt | 8 +-- .../seedvault/settings/SettingsActivity.kt | 17 +++--- .../seedvault/settings/SettingsFragment.kt | 9 +++- .../seedvault/transport/backup/ApkBackup.kt | 2 +- .../seedvault/ui/BackupActivity.kt | 2 +- .../ui/RequireProvisioningActivity.kt | 45 ++++++++-------- .../ui/recoverycode/RecoveryCodeActivity.kt | 2 +- .../recoverycode/RecoveryCodeInputFragment.kt | 14 +++-- .../RecoveryCodeOutputFragment.kt | 12 +++-- .../seedvault/ui/storage/StorageActivity.kt | 13 +---- .../ui/storage/StorageCheckFragment.kt | 15 +++--- .../ui/storage/StorageRootFetcher.kt | 4 +- .../ui/storage/StorageRootsFragment.kt | 54 +++++++++++-------- .../seedvault/ui/storage/StorageViewModel.kt | 20 ++++--- 20 files changed, 149 insertions(+), 121 deletions(-) diff --git a/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt b/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt index 2350bc1e..db4d4c21 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt @@ -11,6 +11,7 @@ import android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED import android.hardware.usb.UsbManager.EXTRA_DEVICE import android.net.Uri import android.os.Handler +import android.os.Looper import android.provider.DocumentsContract import android.util.Log import com.stevesoltys.seedvault.metadata.MetadataManager @@ -74,7 +75,8 @@ abstract class UsbMonitor : BroadcastReceiver() { val rootsUri = DocumentsContract.buildRootsUri(AUTHORITY_STORAGE) val contentResolver = context.contentResolver - val observer = object : ContentObserver(Handler()) { + val handler = Handler(Looper.getMainLooper()) + val observer = object : ContentObserver(handler) { override fun onChange(selfChange: Boolean, uri: Uri?) { super.onChange(selfChange, uri) onStatusChanged(context, action, device) diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt index 3fb0c1c7..9ad6b2f0 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt @@ -7,7 +7,6 @@ import android.content.pm.PackageInfo import android.database.ContentObserver import android.database.Cursor import android.net.Uri -import android.os.FileUtils.closeQuietly import android.provider.DocumentsContract.Document.COLUMN_DOCUMENT_ID import android.provider.DocumentsContract.EXTRA_LOADING import android.provider.DocumentsContract.buildChildDocumentsUriUsingTree @@ -294,14 +293,14 @@ internal suspend fun getLoadedCursor(timeout: Long = 15_000, query: () -> Cursor withTimeout(timeout) { suspendCancellableCoroutine { cont -> val cursor = query() ?: throw IOException() - cont.invokeOnCancellation { closeQuietly(cursor) } + cont.invokeOnCancellation { cursor.close() } val loading = cursor.extras.getBoolean(EXTRA_LOADING, false) if (loading) { Log.d(TAG, "Wait for children to get loaded...") cursor.registerContentObserver(object : ContentObserver(null) { override fun onChange(selfChange: Boolean, uri: Uri?) { Log.d(TAG, "Children loaded. Continue...") - closeQuietly(cursor) + cursor.close() val newCursor = query() if (newCursor == null) cont.cancel(IOException("query returned no results")) else cont.resume(newCursor) diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/InstallProgressFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/InstallProgressFragment.kt index dc56bb44..026e7baf 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/InstallProgressFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/InstallProgressFragment.kt @@ -32,8 +32,11 @@ class InstallProgressFragment : Fragment() { private lateinit var appList: RecyclerView private lateinit var button: Button - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_restore_progress, container, false) progressBar = v.findViewById(R.id.progressBar) @@ -55,20 +58,16 @@ class InstallProgressFragment : Fragment() { } button.setText(R.string.restore_next) button.setOnClickListener { viewModel.onNextClicked() } - } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - viewModel.chosenRestorableBackup.observe(this, Observer { restorableBackup -> + viewModel.chosenRestorableBackup.observe(viewLifecycleOwner, Observer { restorableBackup -> backupNameView.text = restorableBackup.name }) - viewModel.installResult.observe(this, Observer { result -> + viewModel.installResult.observe(viewLifecycleOwner, Observer { result -> onInstallResult(result) }) - viewModel.nextButtonEnabled.observe(this, Observer { enabled -> + viewModel.nextButtonEnabled.observe(viewLifecycleOwner, Observer { enabled -> button.isEnabled = enabled }) } diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreActivity.kt index ff911602..2047b5f1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreActivity.kt @@ -19,7 +19,7 @@ class RestoreActivity : RequireProvisioningActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (isSetupWizard) hideSystemUI() + if (isSetupWizard) hideSystemUiNavigation() setContentView(R.layout.activity_fragment_container) diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt index 69cd69b3..0418945a 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt @@ -59,25 +59,21 @@ class RestoreProgressFragment : Fragment() { requireActivity().setResult(RESULT_OK) requireActivity().finishAfterTransition() } - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) // decryption will fail when the device is locked, so keep the screen on to prevent locking requireActivity().window.addFlags(FLAG_KEEP_SCREEN_ON) - viewModel.chosenRestorableBackup.observe(this, Observer { restorableBackup -> + viewModel.chosenRestorableBackup.observe(viewLifecycleOwner, Observer { restorableBackup -> backupNameView.text = restorableBackup.name progressBar.max = restorableBackup.packageMetadataMap.size }) - viewModel.restoreProgress.observe(this, Observer { list -> + viewModel.restoreProgress.observe(viewLifecycleOwner, Observer { list -> stayScrolledAtTop { adapter.update(list) } progressBar.progress = list.size }) - viewModel.restoreBackupResult.observe(this, Observer { finished -> + viewModel.restoreBackupResult.observe(viewLifecycleOwner, Observer { finished -> button.isEnabled = true if (finished.hasError()) { backupNameView.text = finished.errorMsg diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreSetFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreSetFragment.kt index 49448187..b04a56e6 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreSetFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreSetFragment.kt @@ -24,8 +24,11 @@ class RestoreSetFragment : Fragment() { private lateinit var errorView: TextView private lateinit var backView: TextView - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_restore_set, container, false) listView = v.findViewById(R.id.listView) @@ -36,13 +39,15 @@ class RestoreSetFragment : Fragment() { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) // decryption will fail when the device is locked, so keep the screen on to prevent locking requireActivity().window.addFlags(FLAG_KEEP_SCREEN_ON) - viewModel.restoreSetResults.observe(this, Observer { result -> onRestoreResultsLoaded(result) }) + viewModel.restoreSetResults.observe(viewLifecycleOwner, Observer { result -> + onRestoreResultsLoaded(result) + }) backView.setOnClickListener { requireActivity().finishAfterTransition() } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/AppStatusFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/AppStatusFragment.kt index 255376cb..d1ceef5a 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/AppStatusFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/AppStatusFragment.kt @@ -43,8 +43,8 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) activity?.setTitle(R.string.settings_backup_status_title) @@ -54,7 +54,7 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener { } progressBar.visibility = VISIBLE - viewModel.appStatusList.observe(this, Observer { result -> + viewModel.appStatusList.observe(viewLifecycleOwner, Observer { result -> adapter.update(result.appStatusList, result.diff) progressBar.visibility = INVISIBLE }) @@ -66,7 +66,7 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener { appEditMenuItem = menu.findItem(R.id.edit_app_blacklist) // observe edit mode changes here where we are sure to have the MenuItem - viewModel.appEditMode.observe(this, Observer { enabled -> + viewModel.appEditMode.observe(viewLifecycleOwner, Observer { enabled -> appEditMenuItem.isChecked = enabled adapter.setEditMode(enabled) }) diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsActivity.kt index 064493bc..f3b53d25 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsActivity.kt @@ -5,10 +5,10 @@ import androidx.annotation.CallSuper import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback -import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.ui.RequireProvisioningActivity import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel +import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel @@ -50,13 +50,16 @@ class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmen } } - override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean { - val fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment) - fragment.setTargetFragment(caller, 0) + override fun onPreferenceStartFragment( + caller: PreferenceFragmentCompat, + pref: Preference + ): Boolean { + val fragment = + supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment) supportFragmentManager.beginTransaction() - .replace(R.id.fragment, fragment) - .addToBackStack(null) - .commit() + .replace(R.id.fragment, fragment) + .addToBackStack(null) + .commit() return true } diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt index 5c0ad928..276533a7 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt @@ -16,6 +16,7 @@ import android.util.Log import android.view.Menu import android.view.MenuInflater import android.view.MenuItem +import android.view.View import androidx.appcompat.app.AlertDialog import androidx.lifecycle.Observer import androidx.preference.Preference @@ -117,8 +118,12 @@ class SettingsFragment : PreferenceFragmentCompat() { return@OnPreferenceChangeListener false } backupStatus = findPreference("backup_status")!! + } - viewModel.lastBackupTime.observe(this, Observer { time -> setAppBackupStatusSummary(time) }) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.lastBackupTime.observe(viewLifecycleOwner, Observer { time -> setAppBackupStatusSummary(time) }) } override fun onStart() { @@ -162,7 +167,7 @@ class SettingsFragment : PreferenceFragmentCompat() { true } R.id.action_about -> { - AboutDialogFragment().show(fragmentManager!!, AboutDialogFragment.TAG) + AboutDialogFragment().show(parentFragmentManager, AboutDialogFragment.TAG) true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt index 7258edec..12c4d42b 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt @@ -116,7 +116,7 @@ class ApkBackup( return PackageMetadata( state = packageState, version = version, - installer = pm.getInstallerPackageName(packageName), + installer = pm.getInstallSourceInfo(packageName).installingPackageName, sha256 = sha256, signatures = signatures ) diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/BackupActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/BackupActivity.kt index 7f0d7edf..7d51c7f7 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/BackupActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/BackupActivity.kt @@ -25,7 +25,7 @@ abstract class BackupActivity : AppCompatActivity() { fragmentTransaction.commit() } - protected fun hideSystemUI() { + protected fun hideSystemUiNavigation() { window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_HIDE_NAVIGATION } diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/RequireProvisioningActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/RequireProvisioningActivity.kt index cffe2bfc..f118aab3 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/RequireProvisioningActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/RequireProvisioningActivity.kt @@ -3,14 +3,11 @@ package com.stevesoltys.seedvault.ui import android.content.Intent import android.os.Bundle import android.util.Log +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.annotation.CallSuper import com.stevesoltys.seedvault.ui.recoverycode.RecoveryCodeActivity import com.stevesoltys.seedvault.ui.storage.StorageActivity -const val REQUEST_CODE_OPEN_DOCUMENT_TREE = 1 -const val REQUEST_CODE_BACKUP_LOCATION = 2 -const val REQUEST_CODE_RECOVERY_CODE = 3 - const val INTENT_EXTRA_IS_RESTORE = "isRestore" const val INTENT_EXTRA_IS_SETUP_WIZARD = "isSetupWizard" @@ -24,6 +21,25 @@ private val TAG = RequireProvisioningActivity::class.java.name */ abstract class RequireProvisioningActivity : BackupActivity() { + private val recoveryCodeRequest = + registerForActivityResult(StartActivityForResult()) { result -> + if (result.resultCode != RESULT_OK) { + Log.w(TAG, "Error in activity result for requesting recovery code") + if (!getViewModel().recoveryCodeIsSet()) { + finishAfterTransition() + } + } + } + private val requestLocation = + registerForActivityResult(StartActivityForResult()) { result -> + if (result.resultCode != RESULT_OK) { + Log.w(TAG, "Error in activity result for requesting location") + if (!getViewModel().validLocationIsSet()) { + finishAfterTransition() + } + } + } + protected val isSetupWizard: Boolean get() = intent?.action == ACTION_SETUP_WIZARD @@ -38,35 +54,18 @@ abstract class RequireProvisioningActivity : BackupActivity() { }) } - @CallSuper - override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { - if (requestCode == REQUEST_CODE_BACKUP_LOCATION && resultCode != RESULT_OK) { - Log.w(TAG, "Error in activity result: $requestCode") - if (!getViewModel().validLocationIsSet()) { - finishAfterTransition() - } - } else if (requestCode == REQUEST_CODE_RECOVERY_CODE && resultCode != RESULT_OK) { - Log.w(TAG, "Error in activity result: $requestCode") - if (!getViewModel().recoveryCodeIsSet()) { - finishAfterTransition() - } - } else { - super.onActivityResult(requestCode, resultCode, result) - } - } - protected fun showStorageActivity() { val intent = Intent(this, StorageActivity::class.java) intent.putExtra(INTENT_EXTRA_IS_RESTORE, getViewModel().isRestoreOperation) intent.putExtra(INTENT_EXTRA_IS_SETUP_WIZARD, isSetupWizard) - startActivityForResult(intent, REQUEST_CODE_BACKUP_LOCATION) + requestLocation.launch(intent) } protected fun showRecoveryCodeActivity() { val intent = Intent(this, RecoveryCodeActivity::class.java) intent.putExtra(INTENT_EXTRA_IS_RESTORE, getViewModel().isRestoreOperation) intent.putExtra(INTENT_EXTRA_IS_SETUP_WIZARD, isSetupWizard) - startActivityForResult(intent, REQUEST_CODE_RECOVERY_CODE) + recoveryCodeRequest.launch(intent) } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeActivity.kt index 61270454..4fffe435 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeActivity.kt @@ -16,7 +16,7 @@ class RecoveryCodeActivity : BackupActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (isSetupWizard()) hideSystemUI() + if (isSetupWizard()) hideSystemUiNavigation() setContentView(R.layout.activity_recovery_code) diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt index e604c68a..dce630cf 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt @@ -12,7 +12,7 @@ import android.widget.Button import android.widget.TextView import android.widget.Toast import android.widget.Toast.LENGTH_LONG -import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintLayout import androidx.fragment.app.Fragment import com.google.android.material.textfield.TextInputLayout import com.stevesoltys.seedvault.R @@ -43,8 +43,11 @@ class RecoveryCodeInputFragment : Fragment() { private lateinit var wordLayout12: TextInputLayout private lateinit var wordList: ConstraintLayout - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_recovery_code_input, container, false) introText = v.findViewById(R.id.introText) @@ -67,8 +70,8 @@ class RecoveryCodeInputFragment : Fragment() { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) if (viewModel.isRestore) { introText.setText(R.string.recovery_code_input_intro) @@ -137,6 +140,7 @@ class RecoveryCodeInputFragment : Fragment() { } } + @Suppress("MagicNumber") private fun getWordLayout(i: Int) = when (i + 1) { 1 -> wordLayout1 2 -> wordLayout2 diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeOutputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeOutputFragment.kt index 50d81712..35f6af76 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeOutputFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeOutputFragment.kt @@ -19,8 +19,11 @@ class RecoveryCodeOutputFragment : Fragment() { private lateinit var wordList: RecyclerView private lateinit var confirmCodeButton: Button - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_recovery_code_output, container, false) wordList = v.findViewById(R.id.wordList) @@ -29,8 +32,8 @@ class RecoveryCodeOutputFragment : Fragment() { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) setGridParameters(wordList) wordList.adapter = RecoveryCodeAdapter(viewModel.wordList) @@ -38,6 +41,7 @@ class RecoveryCodeOutputFragment : Fragment() { confirmCodeButton.setOnClickListener { viewModel.onConfirmButtonClicked() } } + @Suppress("MagicNumber") private fun setGridParameters(list: RecyclerView) { val layoutManager = list.layoutManager as GridLayoutManager if (resources.configuration.orientation == ORIENTATION_LANDSCAPE) { diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageActivity.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageActivity.kt index 7534c19b..be1f34e0 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageActivity.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageActivity.kt @@ -1,6 +1,5 @@ package com.stevesoltys.seedvault.ui.storage -import android.content.Intent import android.os.Bundle import android.util.Log import androidx.annotation.CallSuper @@ -22,7 +21,7 @@ class StorageActivity : BackupActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (isSetupWizard()) hideSystemUI() + if (isSetupWizard()) hideSystemUiNavigation() setContentView(R.layout.activity_fragment_container) @@ -52,16 +51,6 @@ class StorageActivity : BackupActivity() { } } - @CallSuper - override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { - if (resultCode != RESULT_OK) { - Log.w(TAG, "Error in activity result: $requestCode") - onInvalidLocation(getString(R.string.storage_check_fragment_permission_error)) - } else { - super.onActivityResult(requestCode, resultCode, result) - } - } - override fun onBackPressed() { if (supportFragmentManager.backStackEntryCount > 0) { Log.d(TAG, "Blocking back button.") diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageCheckFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageCheckFragment.kt index 29da229b..3c8c60d1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageCheckFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageCheckFragment.kt @@ -33,8 +33,11 @@ class StorageCheckFragment : Fragment() { } } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_storage_check, container, false) titleView = v.findViewById(R.id.titleView) @@ -45,12 +48,12 @@ class StorageCheckFragment : Fragment() { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - titleView.text = arguments!!.getString(TITLE) + titleView.text = requireArguments().getString(TITLE) - val errorMsg = arguments!!.getString(ERROR_MSG) + val errorMsg = requireArguments().getString(ERROR_MSG) if (errorMsg != null) { progressBar.visibility = INVISIBLE errorView.text = errorMsg diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt index 76eec4a6..1ef6a385 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt @@ -12,6 +12,7 @@ import android.database.Cursor import android.graphics.drawable.Drawable import android.net.Uri import android.os.Handler +import android.os.Looper import android.provider.DocumentsContract import android.provider.DocumentsContract.PROVIDER_INTERFACE import android.provider.DocumentsContract.Root.COLUMN_AVAILABLE_BYTES @@ -72,7 +73,8 @@ internal class StorageRootFetcher(private val context: Context, private val isRe private val whitelistedAuthorities = context.resources.getStringArray(R.array.storage_authority_whitelist) private var listener: RemovableStorageListener? = null - private val observer = object : ContentObserver(Handler()) { + private val handler = Handler(Looper.getMainLooper()) + private val observer = object : ContentObserver(handler) { override fun onChange(selfChange: Boolean, uri: Uri?) { super.onChange(selfChange, uri) listener?.onStorageChanged() diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootsFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootsFragment.kt index bafb074d..5f5b2a54 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootsFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootsFragment.kt @@ -1,9 +1,12 @@ package com.stevesoltys.seedvault.ui.storage +import android.annotation.SuppressLint +import android.content.Context import android.content.Intent import android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -13,13 +16,12 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.ProgressBar import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity.RESULT_OK +import androidx.activity.result.contract.ActivityResultContracts.OpenDocumentTree import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.recyclerview.widget.RecyclerView import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.ui.INTENT_EXTRA_IS_RESTORE -import com.stevesoltys.seedvault.ui.REQUEST_CODE_OPEN_DOCUMENT_TREE import org.koin.androidx.viewmodel.ext.android.getSharedViewModel internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { @@ -45,8 +47,11 @@ internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { private val adapter by lazy { StorageRootAdapter(viewModel.isRestoreOperation, this) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val v: View = inflater.inflate(R.layout.fragment_storage_root, container, false) titleView = v.findViewById(R.id.titleView) @@ -60,10 +65,10 @@ internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { return v } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - viewModel = if (arguments!!.getBoolean(INTENT_EXTRA_IS_RESTORE)) { + viewModel = if (requireArguments().getBoolean(INTENT_EXTRA_IS_RESTORE)) { getSharedViewModel() } else { getSharedViewModel() @@ -81,7 +86,9 @@ internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { listView.adapter = adapter - viewModel.storageRoots.observe(this, Observer { roots -> onRootsLoaded(roots) }) + viewModel.storageRoots.observe(viewLifecycleOwner, Observer { roots -> + onRootsLoaded(roots) + }) } override fun onStart() { @@ -94,21 +101,13 @@ internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { adapter.setItems(roots) } - override fun onClick(root: StorageRoot) { - viewModel.onStorageRootChosen(root) - val intent = Intent(requireContext(), PermissionGrantActivity::class.java) - intent.data = root.uri - intent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION or - FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION) - startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE) + private val openDocumentTree = registerForActivityResult(OpenSeedvaultTree()) { uri -> + viewModel.onUriPermissionResultReceived(uri) } - override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { - if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_OPEN_DOCUMENT_TREE) { - viewModel.onUriPermissionGranted(result) - } else { - super.onActivityResult(requestCode, resultCode, result) - } + override fun onClick(root: StorageRoot) { + viewModel.onStorageRootChosen(root) + openDocumentTree.launch(root.uri) } } @@ -116,3 +115,16 @@ internal class StorageRootsFragment : Fragment(), StorageRootClickedListener { internal interface StorageRootClickedListener { fun onClick(root: StorageRoot) } + +private class OpenSeedvaultTree : OpenDocumentTree() { + @SuppressLint("MissingSuperCall") // we are intentionally creating our own intent + override fun createIntent(context: Context, input: Uri?): Intent { + return Intent(context, PermissionGrantActivity::class.java).apply { + check(input != null) { "Uri was null, but is needed." } + data = input + val flags = FLAG_GRANT_PERSISTABLE_URI_PERMISSION or + FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION + addFlags(flags) + } + } +} diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt index 6a99ff62..ea824aa1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt @@ -3,7 +3,6 @@ package com.stevesoltys.seedvault.ui.storage import android.app.Application import android.content.Context import android.content.Context.USB_SERVICE -import android.content.Intent import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION import android.hardware.usb.UsbManager @@ -24,8 +23,8 @@ import com.stevesoltys.seedvault.ui.MutableLiveEvent private val TAG = StorageViewModel::class.java.simpleName internal abstract class StorageViewModel( - private val app: Application, - protected val settingsManager: SettingsManager + private val app: Application, + protected val settingsManager: SettingsManager ) : AndroidViewModel(app), RemovableStorageListener { private val mStorageRoots = MutableLiveData>() @@ -44,7 +43,10 @@ internal abstract class StorageViewModel( abstract val isRestoreOperation: Boolean companion object { - internal fun validLocationIsSet(context: Context, settingsManager: SettingsManager): Boolean { + internal fun validLocationIsSet( + context: Context, + settingsManager: SettingsManager + ): Boolean { val storage = settingsManager.getStorage() ?: return false if (storage.isUsb) return true return storage.getDocumentFile(context).isDirectory @@ -66,14 +68,18 @@ internal abstract class StorageViewModel( storageRoot = root } - internal fun onUriPermissionGranted(result: Intent?) { - val uri = result?.data ?: return + internal fun onUriPermissionResultReceived(uri: Uri?) { + if (uri == null) { + val msg = app.getString(R.string.storage_check_fragment_permission_error) + mLocationChecked.setEvent(LocationResult(msg)) + return + } // inform UI that a location has been successfully selected mLocationSet.setEvent(true) // persist permission to access backup folder across reboots - val takeFlags = result.flags and (FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION) + val takeFlags = FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION app.contentResolver.takePersistableUriPermission(uri, takeFlags) onLocationSet(uri)