Skip to content

Commit

Permalink
Address book android auto backup (#1641)
Browse files Browse the repository at this point in the history
* Address book android auto backup

* Documentation update

* Address book container folder added

* Address book general error handling

* Address book memory storage hotfix

* Documentation update

---------

Co-authored-by: Honza <[email protected]>
  • Loading branch information
Milan-Cerovsky and HonzaR authored Nov 15, 2024
1 parent 95285c5 commit 32b1329
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this application adheres to [Semantic Versioning](https://semver.org/spec/v2

### Added
- Address book encryption
- Android auto backup support for address book encryption
- The device authentication feature on the Zashi app launch has been added
- Zashi app now supports Spanish language. It can be changed in the System settings options.
- The Flexa SDK has been adopted to enable payments using the embedded Flexa UI
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

<application
android:name="co.electriccoin.zcash.app.ZcashApplication"
android:allowBackup="false"
android:allowBackup="true"
android:fullBackupContent="@xml/auto_backup_config"
android:dataExtractionRules="@xml/auto_backup_config_android_12"
android:backupInForeground="true"
android:icon="@mipmap/ic_launcher_square"
android:roundIcon="@mipmap/ic_launcher_round"
android:localeConfig="@xml/locales_config"
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/xml/auto_backup_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include
domain="file"
path="address_book/." />
</full-backup-content>
8 changes: 8 additions & 0 deletions app/src/main/res/xml/auto_backup_config_android_12.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup disableIfNoEncryptionCapabilities="false">
<include
domain="file"
path="address_book/." />
</cloud-backup>
</data-extraction-rules>
1 change: 0 additions & 1 deletion app/src/zcashmainnetDebug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

<application
android:name="co.electriccoin.zcash.app.ZcashApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher_square"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name">
Expand Down
1 change: 0 additions & 1 deletion app/src/zcashtestnet/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

<application
android:name="co.electriccoin.zcash.app.ZcashApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher_square"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name">
Expand Down
1 change: 0 additions & 1 deletion app/src/zcashtestnetDebug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

<application
android:name="co.electriccoin.zcash.app.ZcashApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher_square"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name">
Expand Down
9 changes: 7 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Documentation

Here you'll find documentation
TBD
# Android auto backup testing

To force the android system back up the app use the following commands:
```
adb shell bmgr enable true
adb shell bmgr backupnow co.electriccoin.zcash.debug
```
1 change: 1 addition & 0 deletions docs/whatsNew/WHATS_NEW_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ directly impact users rather than highlighting other key architectural updates.*

### Added
- Address book encryption
- Android auto backup support for address book encryption
- The device authentication feature on the Zashi app launch has been added
- Zashi app now supports Spanish language. It can be changed in the System settings options.
- The Flexa SDK has been adopted to enable payments using the embedded Flexa UI
Expand Down
1 change: 1 addition & 0 deletions docs/whatsNew/WHATS_NEW_ES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ directly impact users rather than highlighting other key architectural updates.*

### Added
- Address book encryption
- Android auto backup support for address book encryption
- The device authentication feature on the Zashi app launch has been added
- Zashi app now supports Spanish language. It can be changed in the System settings options.
- The Flexa SDK has been adopted to enable payments using the embedded Flexa UI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import co.electriccoin.zcash.ui.common.serialization.addressbook.AddressBookKey
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
import java.io.IOException
import java.security.GeneralSecurityException

interface LocalAddressBookDataSource {
suspend fun getContacts(addressBookKey: AddressBookKey): AddressBook
Expand Down Expand Up @@ -61,7 +59,9 @@ class LocalAddressBookDataSourceImpl(
lastUpdated = Clock.System.now(),
version = ADDRESS_BOOK_SERIALIZATION_V1,
contacts = emptyList(),
)
).also {
this@LocalAddressBookDataSourceImpl.addressBook = it
}
writeAddressBookToLocalStorage(newAddressBook, addressBookKey)
}
newAddressBook
Expand All @@ -88,7 +88,9 @@ class LocalAddressBookDataSourceImpl(
address = address,
lastUpdated = lastUpdated,
),
)
).also {
addressBook = it
}
writeAddressBookToLocalStorage(newAddressBook, addressBookKey)
newAddressBook
}
Expand Down Expand Up @@ -118,7 +120,9 @@ class LocalAddressBookDataSourceImpl(
)
}
.toList(),
)
).also {
addressBook = it
}
writeAddressBookToLocalStorage(newAddressBook, addressBookKey)
newAddressBook
}
Expand All @@ -139,7 +143,9 @@ class LocalAddressBookDataSourceImpl(
remove(addressBookContact)
}
.toList(),
)
).also {
addressBook = it
}
writeAddressBookToLocalStorage(newAddressBook, addressBookKey)
newAddressBook
}
Expand All @@ -158,22 +164,15 @@ class LocalAddressBookDataSourceImpl(

@Suppress("ReturnCount")
private suspend fun readLocalFileToAddressBook(addressBookKey: AddressBookKey): AddressBook? {
val encryptedFile = addressBookStorageProvider.getStorageFile(addressBookKey)
val unencryptedFile = addressBookStorageProvider.getLegacyUnencryptedStorageFile()
val encryptedFile = runCatching { addressBookStorageProvider.getStorageFile(addressBookKey) }.getOrNull()
val unencryptedFile = runCatching { addressBookStorageProvider.getLegacyUnencryptedStorageFile() }.getOrNull()

if (encryptedFile != null) {
return try {
addressBookProvider.readAddressBookFromFile(encryptedFile, addressBookKey)
.also {
unencryptedFile?.deleteSuspend()
}
} catch (e: GeneralSecurityException) {
Twig.warn(e) { "Failed to decrypt address book" }
null
} catch (e: IOException) {
Twig.warn(e) { "Failed to decrypt address book" }
null
}
return runCatching {
addressBookProvider
.readAddressBookFromFile(encryptedFile, addressBookKey)
.also { unencryptedFile?.deleteSuspend() }
}.onFailure { e -> Twig.warn(e) { "Failed to decrypt address book" } }.getOrNull()
}

return if (unencryptedFile != null) {
Expand All @@ -191,7 +190,9 @@ class LocalAddressBookDataSourceImpl(
addressBook: AddressBook,
addressBookKey: AddressBookKey
) {
val file = addressBookStorageProvider.getOrCreateStorageFile(addressBookKey)
addressBookProvider.writeAddressBookToFile(file, addressBook, addressBookKey)
runCatching {
val file = addressBookStorageProvider.getOrCreateStorageFile(addressBookKey)
addressBookProvider.writeAddressBookToFile(file, addressBook, addressBookKey)
}.onFailure { e -> Twig.warn(e) { "Failed to write address book" } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ interface AddressBookStorageProvider {

fun getOrCreateStorageFile(addressBookKey: AddressBookKey): File

/**
* Create a temporary file into which data from remote is written. This file is removed after usage.
*/
fun getOrCreateTempStorageFile(): File
// /**
// * Create a temporary file into which data from remote is written. This file is removed after usage.
// */
// fun getOrCreateTempStorageFile(): File
}

class AddressBookStorageProviderImpl(
private val context: Context
) : AddressBookStorageProvider {
override fun getStorageFile(addressBookKey: AddressBookKey): File? {
return File(context.noBackupFilesDir, addressBookKey.fileIdentifier())
return File(getOrCreateAddressBookDir(), addressBookKey.fileIdentifier())
.takeIf { it.exists() && it.isFile }
}

Expand All @@ -31,19 +31,30 @@ class AddressBookStorageProviderImpl(
}

override fun getOrCreateStorageFile(addressBookKey: AddressBookKey): File {
return getOrCreateFile(addressBookKey.fileIdentifier())
}

override fun getOrCreateTempStorageFile(): File = getOrCreateFile(REMOTE_ADDRESS_BOOK_FILE_NAME_LOCAL_COPY)

private fun getOrCreateFile(name: String): File {
val file = File(context.noBackupFilesDir, name)
val file = File(getOrCreateAddressBookDir(), addressBookKey.fileIdentifier())
if (!file.exists()) {
file.createNewFile()
}
return file
}

// override fun getOrCreateTempStorageFile(): File {
// val file = File(context.noBackupFilesDir, REMOTE_ADDRESS_BOOK_FILE_NAME_LOCAL_COPY)
// if (!file.exists()) {
// file.createNewFile()
// }
// return file
// }

private fun getOrCreateAddressBookDir(): File {
val filesDir = context.filesDir
val addressBookDir = File(filesDir, "address_book")
if (!addressBookDir.exists()) {
addressBookDir.mkdir()
}
return addressBookDir
}
}

private const val LEGACY_UNENCRYPTED_ADDRESS_BOOK_FILE_NAME = "address_book"
private const val REMOTE_ADDRESS_BOOK_FILE_NAME_LOCAL_COPY = "address_book_temp"
// private const val REMOTE_ADDRESS_BOOK_FILE_NAME_LOCAL_COPY = "address_book_temp"

0 comments on commit 32b1329

Please sign in to comment.