Show Backup Location screen before letting user choose backup folder
This screen can also be reached by tapping the previously inactive backup location setting.
This commit is contained in:
parent
3e64c3686f
commit
4c79d41963
9 changed files with 163 additions and 51 deletions
|
@ -0,0 +1,59 @@
|
||||||
|
package com.stevesoltys.backup.settings
|
||||||
|
|
||||||
|
import android.app.Activity.RESULT_OK
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.Intent.*
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import android.widget.Toast.LENGTH_LONG
|
||||||
|
import androidx.lifecycle.ViewModelProviders
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import com.stevesoltys.backup.R
|
||||||
|
|
||||||
|
private val TAG = BackupLocationFragment::class.java.name
|
||||||
|
|
||||||
|
class BackupLocationFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
private lateinit var viewModel: SettingsViewModel
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.backup_location, rootKey)
|
||||||
|
|
||||||
|
requireActivity().setTitle(R.string.settings_backup_location_title)
|
||||||
|
|
||||||
|
viewModel = ViewModelProviders.of(requireActivity()).get(SettingsViewModel::class.java)
|
||||||
|
|
||||||
|
val externalStorage = Preference(requireContext()).apply {
|
||||||
|
setIcon(R.drawable.ic_storage)
|
||||||
|
setTitle(R.string.settings_backup_external_storage)
|
||||||
|
setOnPreferenceClickListener {
|
||||||
|
showChooseFolderActivity()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preferenceScreen.addPreference(externalStorage)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showChooseFolderActivity() {
|
||||||
|
val openTreeIntent = Intent(ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
openTreeIntent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||||
|
FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
try {
|
||||||
|
val documentChooser = createChooser(openTreeIntent, null)
|
||||||
|
startActivityForResult(documentChooser, REQUEST_CODE_OPEN_DOCUMENT_TREE)
|
||||||
|
} catch (ex: ActivityNotFoundException) {
|
||||||
|
Toast.makeText(requireContext(), "Please install a file manager.", LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
|
||||||
|
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_OPEN_DOCUMENT_TREE) {
|
||||||
|
viewModel.handleChooseFolderResult(result)
|
||||||
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.stevesoltys.backup.settings
|
package com.stevesoltys.backup.settings
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.ByteStringUtils.toHexString
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import com.stevesoltys.backup.LiveEvent
|
import com.stevesoltys.backup.LiveEvent
|
||||||
import com.stevesoltys.backup.MutableLiveEvent
|
import com.stevesoltys.backup.MutableLiveEvent
|
||||||
|
@ -33,7 +34,8 @@ class RecoveryCodeViewModel(application: Application) : AndroidViewModel(applica
|
||||||
internal val confirmButtonClicked: LiveEvent<Boolean> = mConfirmButtonClicked
|
internal val confirmButtonClicked: LiveEvent<Boolean> = mConfirmButtonClicked
|
||||||
internal fun onConfirmButtonClicked() = mConfirmButtonClicked.setEvent(true)
|
internal fun onConfirmButtonClicked() = mConfirmButtonClicked.setEvent(true)
|
||||||
|
|
||||||
internal val recoveryCodeSaved = MutableLiveEvent<Boolean>()
|
private val mRecoveryCodeSaved = MutableLiveEvent<Boolean>()
|
||||||
|
internal val recoveryCodeSaved: LiveEvent<Boolean> = mRecoveryCodeSaved
|
||||||
|
|
||||||
@Throws(WordNotFoundException::class, InvalidChecksumException::class)
|
@Throws(WordNotFoundException::class, InvalidChecksumException::class)
|
||||||
fun validateAndContinue(input: List<CharSequence>) {
|
fun validateAndContinue(input: List<CharSequence>) {
|
||||||
|
@ -47,7 +49,11 @@ class RecoveryCodeViewModel(application: Application) : AndroidViewModel(applica
|
||||||
val mnemonic = input.joinToString(" ")
|
val mnemonic = input.joinToString(" ")
|
||||||
val seed = SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(mnemonic, "")
|
val seed = SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(mnemonic, "")
|
||||||
KeyManager.storeBackupKey(seed)
|
KeyManager.storeBackupKey(seed)
|
||||||
recoveryCodeSaved.setEvent(true)
|
|
||||||
|
// TODO remove once encryption/decryption uses key from KeyStore
|
||||||
|
setBackupPassword(getApplication(), toHexString(seed))
|
||||||
|
|
||||||
|
mRecoveryCodeSaved.setEvent(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package com.stevesoltys.backup.settings
|
package com.stevesoltys.backup.settings
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.Intent.*
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.Toast
|
|
||||||
import android.widget.Toast.LENGTH_LONG
|
|
||||||
import android.widget.Toast.LENGTH_SHORT
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
|
import com.stevesoltys.backup.LiveEventHandler
|
||||||
import com.stevesoltys.backup.R
|
import com.stevesoltys.backup.R
|
||||||
|
|
||||||
private val TAG = SettingsActivity::class.java.name
|
private val TAG = SettingsActivity::class.java.name
|
||||||
|
@ -19,7 +15,6 @@ private val TAG = SettingsActivity::class.java.name
|
||||||
const val REQUEST_CODE_OPEN_DOCUMENT_TREE = 1
|
const val REQUEST_CODE_OPEN_DOCUMENT_TREE = 1
|
||||||
const val REQUEST_CODE_RECOVERY_CODE = 2
|
const val REQUEST_CODE_RECOVERY_CODE = 2
|
||||||
|
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var viewModel: SettingsViewModel
|
private lateinit var viewModel: SettingsViewModel
|
||||||
|
@ -30,18 +25,25 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
|
|
||||||
viewModel = ViewModelProviders.of(this).get(SettingsViewModel::class.java)
|
viewModel = ViewModelProviders.of(this).get(SettingsViewModel::class.java)
|
||||||
|
viewModel.onLocationSet.observeEvent(this, LiveEventHandler { wasEmptyBefore ->
|
||||||
|
if (wasEmptyBefore) showFragment(SettingsFragment())
|
||||||
|
else supportFragmentManager.popBackStack()
|
||||||
|
})
|
||||||
|
viewModel.chooseBackupLocation.observeEvent(this, LiveEventHandler { show ->
|
||||||
|
if (show) showFragment(BackupLocationFragment(), true)
|
||||||
|
})
|
||||||
|
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) showFragment(SettingsFragment())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
|
||||||
if (resultCode != RESULT_OK) {
|
if (resultCode != RESULT_OK) {
|
||||||
Log.w(TAG, "Error in activity result: $requestCode")
|
Log.w(TAG, "Error in activity result: $requestCode")
|
||||||
finishAfterTransition()
|
finishAfterTransition()
|
||||||
}
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, result)
|
||||||
if (requestCode == REQUEST_CODE_OPEN_DOCUMENT_TREE) {
|
|
||||||
viewModel.handleChooseFolderResult(result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,34 +55,16 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
if (!viewModel.recoveryCodeIsSet()) {
|
if (!viewModel.recoveryCodeIsSet()) {
|
||||||
showRecoveryCodeActivity()
|
showRecoveryCodeActivity()
|
||||||
} else if (!viewModel.locationIsSet()) {
|
} else if (!viewModel.locationIsSet()) {
|
||||||
showChooseFolderActivity()
|
showFragment(BackupLocationFragment())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean = when {
|
||||||
menuInflater.inflate(R.menu.settings_menu, menu)
|
item.itemId == android.R.id.home -> {
|
||||||
if (resources.getBoolean(R.bool.show_restore_in_settings)) {
|
onBackPressed()
|
||||||
menu.findItem(R.id.action_restore).isVisible = true
|
true
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
return when {
|
|
||||||
item.itemId == android.R.id.home -> {
|
|
||||||
onBackPressed()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
item.itemId == R.id.action_backup -> {
|
|
||||||
Toast.makeText(this, "Not yet implemented", LENGTH_SHORT).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
item.itemId == R.id.action_restore -> {
|
|
||||||
Toast.makeText(this, "Not yet implemented", LENGTH_SHORT).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
|
||||||
}
|
}
|
||||||
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showRecoveryCodeActivity() {
|
private fun showRecoveryCodeActivity() {
|
||||||
|
@ -88,17 +72,11 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
startActivityForResult(intent, REQUEST_CODE_RECOVERY_CODE)
|
startActivityForResult(intent, REQUEST_CODE_RECOVERY_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showChooseFolderActivity() {
|
private fun showFragment(f: Fragment, addToBackStack: Boolean = false) {
|
||||||
val openTreeIntent = Intent(ACTION_OPEN_DOCUMENT_TREE)
|
val fragmentTransaction = supportFragmentManager.beginTransaction()
|
||||||
openTreeIntent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
.replace(R.id.fragment, f)
|
||||||
FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
|
if (addToBackStack) fragmentTransaction.addToBackStack(null)
|
||||||
// TODO StringRes
|
fragmentTransaction.commit()
|
||||||
try {
|
|
||||||
val documentChooser = createChooser(openTreeIntent, "Select the backup location")
|
|
||||||
startActivityForResult(documentChooser, REQUEST_CODE_OPEN_DOCUMENT_TREE)
|
|
||||||
} catch (ex: ActivityNotFoundException) {
|
|
||||||
Toast.makeText(this, "Please install a file manager.", LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ import com.stevesoltys.backup.R
|
||||||
import android.content.Context.BACKUP_SERVICE
|
import android.content.Context.BACKUP_SERVICE
|
||||||
import android.os.ServiceManager.getService
|
import android.os.ServiceManager.getService
|
||||||
import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE
|
import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.Preference.OnPreferenceChangeListener
|
import androidx.preference.Preference.OnPreferenceChangeListener
|
||||||
|
|
||||||
|
@ -24,14 +29,19 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
private lateinit var backupManager: IBackupManager
|
private lateinit var backupManager: IBackupManager
|
||||||
|
|
||||||
|
private lateinit var viewModel: SettingsViewModel
|
||||||
|
|
||||||
private lateinit var backup: TwoStatePreference
|
private lateinit var backup: TwoStatePreference
|
||||||
private lateinit var autoRestore: TwoStatePreference
|
private lateinit var autoRestore: TwoStatePreference
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.settings, rootKey)
|
setPreferencesFromResource(R.xml.settings, rootKey)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
|
||||||
backupManager = IBackupManager.Stub.asInterface(getService(BACKUP_SERVICE))
|
backupManager = IBackupManager.Stub.asInterface(getService(BACKUP_SERVICE))
|
||||||
|
|
||||||
|
viewModel = ViewModelProviders.of(requireActivity()).get(SettingsViewModel::class.java)
|
||||||
|
|
||||||
backup = findPreference("backup") as TwoStatePreference
|
backup = findPreference("backup") as TwoStatePreference
|
||||||
backup.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue ->
|
backup.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue ->
|
||||||
val enabled = newValue as Boolean
|
val enabled = newValue as Boolean
|
||||||
|
@ -45,6 +55,12 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backupLocation = findPreference("backup_location")
|
||||||
|
backupLocation.setOnPreferenceClickListener {
|
||||||
|
viewModel.chooseBackupLocation()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
autoRestore = findPreference("auto_restore") as TwoStatePreference
|
autoRestore = findPreference("auto_restore") as TwoStatePreference
|
||||||
autoRestore.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue ->
|
autoRestore.onPreferenceChangeListener = OnPreferenceChangeListener { _, newValue ->
|
||||||
val enabled = newValue as Boolean
|
val enabled = newValue as Boolean
|
||||||
|
@ -62,6 +78,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
|
// we need to re-set the title when returning to this fragment
|
||||||
|
requireActivity().setTitle(R.string.app_name)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
backup.isChecked = backupManager.isBackupEnabled
|
backup.isChecked = backupManager.isBackupEnabled
|
||||||
backup.isEnabled = true
|
backup.isEnabled = true
|
||||||
|
@ -74,4 +93,24 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
autoRestore.isChecked = Settings.Secure.getInt(resolver, BACKUP_AUTO_RESTORE, 1) == 1
|
autoRestore.isChecked = Settings.Secure.getInt(resolver, BACKUP_AUTO_RESTORE, 1) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
inflater.inflate(R.menu.settings_menu, menu)
|
||||||
|
if (resources.getBoolean(R.bool.show_restore_in_settings)) {
|
||||||
|
menu.findItem(R.id.action_restore).isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean = when {
|
||||||
|
item.itemId == R.id.action_backup -> {
|
||||||
|
Toast.makeText(requireContext(), "Not yet implemented", Toast.LENGTH_SHORT).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
item.itemId == R.id.action_restore -> {
|
||||||
|
Toast.makeText(requireContext(), "Not yet implemented", Toast.LENGTH_SHORT).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,25 @@ import android.content.Intent
|
||||||
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
|
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
import android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import com.stevesoltys.backup.LiveEvent
|
||||||
|
import com.stevesoltys.backup.MutableLiveEvent
|
||||||
import com.stevesoltys.backup.security.KeyManager
|
import com.stevesoltys.backup.security.KeyManager
|
||||||
|
|
||||||
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
|
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
private val app = application
|
private val app = application
|
||||||
|
|
||||||
|
private val mLocationWasSet = MutableLiveEvent<Boolean>()
|
||||||
|
/**
|
||||||
|
* Will be set to true if this is the initial location.
|
||||||
|
* It will be false if an existing location was changed.
|
||||||
|
*/
|
||||||
|
internal val onLocationSet: LiveEvent<Boolean> = locationWasSet
|
||||||
|
|
||||||
|
private val mChooseBackupLocation = MutableLiveEvent<Boolean>()
|
||||||
|
internal val chooseBackupLocation: LiveEvent<Boolean> = mChooseBackupLocation
|
||||||
|
internal fun chooseBackupLocation() = mChooseBackupLocation.setEvent(true)
|
||||||
|
|
||||||
fun recoveryCodeIsSet() = KeyManager.hasBackupKey()
|
fun recoveryCodeIsSet() = KeyManager.hasBackupKey()
|
||||||
fun locationIsSet() = getBackupFolderUri(getApplication()) != null
|
fun locationIsSet() = getBackupFolderUri(getApplication()) != null
|
||||||
|
|
||||||
|
@ -21,8 +34,14 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
|
||||||
val takeFlags = result.flags and (FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
|
val takeFlags = result.flags and (FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
app.contentResolver.takePersistableUriPermission(folderUri, takeFlags)
|
app.contentResolver.takePersistableUriPermission(folderUri, takeFlags)
|
||||||
|
|
||||||
|
// check if this is initial set-up or a later change
|
||||||
|
val wasEmptyBefore = getBackupFolderUri(app) == null
|
||||||
|
|
||||||
// store backup folder location in settings
|
// store backup folder location in settings
|
||||||
setBackupFolderUri(app, folderUri)
|
setBackupFolderUri(app, folderUri)
|
||||||
|
|
||||||
|
// notify the UI that the location has been set
|
||||||
|
mLocationWasSet.setEvent(wasEmptyBefore)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/fragment"
|
android:id="@+id/fragment"
|
||||||
android:name="com.stevesoltys.backup.settings.SettingsFragment"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
|
@ -26,6 +26,8 @@
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="settings_backup">Backup my data</string>
|
<string name="settings_backup">Backup my data</string>
|
||||||
<string name="settings_backup_location">Backup location</string>
|
<string name="settings_backup_location">Backup location</string>
|
||||||
|
<string name="settings_backup_location_title">Backup Location</string>
|
||||||
|
<string name="settings_backup_location_info">Choose where to store your backups. More options might get added in the future.</string>
|
||||||
<string name="settings_backup_external_storage">External Storage</string>
|
<string name="settings_backup_external_storage">External Storage</string>
|
||||||
<string name="settings_info">All backups are encrypted on your phone. To restore from backup you will need your 12-word recovery code.</string>
|
<string name="settings_info">All backups are encrypted on your phone. To restore from backup you will need your 12-word recovery code.</string>
|
||||||
<string name="settings_auto_restore_title">Automatic restore</string>
|
<string name="settings_auto_restore_title">Automatic restore</string>
|
||||||
|
|
11
app/src/main/res/xml/backup_location.xml
Normal file
11
app/src/main/res/xml/backup_location.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<androidx.preference.Preference
|
||||||
|
app:allowDividerAbove="true"
|
||||||
|
app:allowDividerBelow="false"
|
||||||
|
app:icon="@drawable/ic_info_outline"
|
||||||
|
app:selectable="false"
|
||||||
|
app:order="1337"
|
||||||
|
app:summary="@string/settings_backup_location_info" />
|
||||||
|
|
||||||
|
</androidx.preference.PreferenceScreen>
|
|
@ -10,7 +10,6 @@
|
||||||
app:dependency="backup"
|
app:dependency="backup"
|
||||||
app:icon="@drawable/ic_storage"
|
app:icon="@drawable/ic_storage"
|
||||||
app:key="backup_location"
|
app:key="backup_location"
|
||||||
app:selectable="false"
|
|
||||||
app:summary="@string/settings_backup_external_storage"
|
app:summary="@string/settings_backup_external_storage"
|
||||||
app:title="@string/settings_backup_location" />
|
app:title="@string/settings_backup_location" />
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue