View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0012090 | Taler | wallet (Android App) | public | 2026-11-11 01:44 | 2026-11-11 01:44 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | minor | Reproducibility | have not tried |
| Status | new | Resolution | open | ||
| Summary | 0012090: Android: database export/import and the app version are only visible in developer mode (app version: regression of 0008536) -- iOS and the WebExtension offer backup/restore to everybody (patch attached) | ||||
| Description | On Android, a user who has not switched on developer mode can neither back up the wallet database (Export database / Import database) nor see which app version is installed. All of these rows sit inside the developer-mode block of Settings. iOS offers "Backup / Restore" (More settings) and shows "App Version" and "Wallet-Core Version" under "About GNU Taler" to everybody; the WebExtension offers "Database export and import" in its normal settings. For the app version this is a regression of 0008536 ("show version info even when not in developer mode", fixed in b3119118: app version shown by default, wallet-core version developer-only). The Compose migration (2cede292, 2026-04-22) moved the app version into the developer block; before it, settings_main.xml had pref_version_app with isPreferenceVisible="true" and it was not in SettingsFragment's devPrefs list. Export/import were already developer-only then. What the user sees (developer mode off): - Android: Payment services, Bank accounts, Tax-deductible donations, Protect access to wallet, Developer mode, and nothing else (before-android-1.png). The export/import/version rows appear only with developer mode on, next to "Reset Wallet (dangerous!)" and the integration test (before-android-2.png). - iOS: Settings starts with "About GNU Taler" (App Version 1.6.18, Wallet-Core Version 1.6.49), More > "Backup / Restore" with "Create JSON backup" / restore list (before-ios-1.png .. before-ios-4.png). - WebExtension: Settings > "Database export and import" with a warning that exports contain sensitive data (before-web-1.png). Why it matters: the wallet holds money, and uninstalling or losing the phone loses it (0010681). The only backup the Android app has is hidden behind a switch labelled "Shows more information intended for debugging". Support also cannot ask an ordinary user for the app version. Code (origin/master 4c483527): - wallet/src/main/java/net/taler/wallet/settings/SettingsScreen.kt:240 `if (devModeEnabled) {`, then :310-316 Export database, :324-338 Import database, :348-358 App version / Wallet Core version; the export confirmation dialog (pendingDbExport, :408-433) is also inside the block. The patch (android-F408-backup-and-version-visible.patch, SettingsScreen.kt only): moves "Export database" (JSON, with its existing "sensitive data" confirmation), "Import database" (with its existing confirmation) and "App version" above the Developer mode switch, and moves the export confirmation dialog out of the developer block so it also works with developer mode off. Raw SQLite export, the wallet-core and protocol versions (as decided in 0008536), integration test and reset stay developer-only. No new strings. Verified: :wallet:assembleFdroidSim and :wallet:testFdroidSimUnitTest pass; after-android-1.png (Export/Import database and App version visible with developer mode off) and after-android-2.png (export confirmation dialog with developer mode off). Related, not changed here: 0011037 (Android lacks the diagnostics export iOS and web have), 0011844 (DD92 backup & sync UI). Assisted by LLM | ||||
| Steps To Reproduce | 1. Fresh install, developer mode off. 2. Settings: no Export/Import database, no App version. 3. Switch on Developer mode: the rows appear. | ||||
| Tags | No tags attached. | ||||
| Attached Files | android-F408-backup-and-version-visible.patch (7,122 bytes)
diff --git a/wallet/src/main/java/net/taler/wallet/settings/SettingsScreen.kt b/wallet/src/main/java/net/taler/wallet/settings/SettingsScreen.kt
index 05923069..9e9a2f30 100644
--- a/wallet/src/main/java/net/taler/wallet/settings/SettingsScreen.kt
+++ b/wallet/src/main/java/net/taler/wallet/settings/SettingsScreen.kt
@@ -227,6 +227,36 @@ fun SettingsContent(
}
)
+ SettingsItem(
+ title = stringResource(R.string.settings_db_export),
+ summary = stringResource(R.string.settings_db_export_summary),
+ icon = ImageVector.vectorResource(R.drawable.ic_unarchive),
+ onClick = { pendingDbExport = DbExportType.Json }
+ )
+
+ SettingsItem(
+ title = stringResource(R.string.settings_db_import),
+ summary = stringResource(R.string.settings_db_import_summary),
+ icon = ImageVector.vectorResource(R.drawable.ic_archive),
+ onClick = {
+ MaterialAlertDialogBuilder(context)
+ .setMessage(R.string.settings_dialog_import_message)
+ .setNegativeButton(R.string.import_db) { _, _ ->
+ dbImportLauncher.launch(arrayOf("application/json"))
+ }
+ .setPositiveButton(R.string.cancel) { _, _ ->
+ scope.launch { snackbarHostState.showSnackbar(importCanceledMessage) }
+ }
+ .show()
+ }
+ )
+
+ SettingsItem(
+ title = stringResource(R.string.settings_version_app),
+ summary = "${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR} ${BuildConfig.VERSION_CODE})",
+ icon = ImageVector.vectorResource(R.drawable.ic_account_balance_wallet),
+ )
+
SettingsSwitchItem(
title = stringResource(R.string.settings_dev_mode),
summary = stringResource(R.string.settings_dev_mode_summary),
@@ -308,13 +338,6 @@ fun SettingsContent(
onClick = { onNavigate(WalletDestination.AliasRegistration, false) }
)
- SettingsItem(
- title = stringResource(R.string.settings_db_export),
- summary = stringResource(R.string.settings_db_export_summary),
- icon = ImageVector.vectorResource(R.drawable.ic_unarchive),
- onClick = { pendingDbExport = DbExportType.Json }
- )
-
SettingsItem(
title = stringResource(R.string.settings_db_export_raw),
summary = stringResource(R.string.settings_db_export_raw_summary),
@@ -322,23 +345,6 @@ fun SettingsContent(
onClick = { pendingDbExport = DbExportType.Raw }
)
- SettingsItem(
- title = stringResource(R.string.settings_db_import),
- summary = stringResource(R.string.settings_db_import_summary),
- icon = ImageVector.vectorResource(R.drawable.ic_archive),
- onClick = {
- MaterialAlertDialogBuilder(context)
- .setMessage(R.string.settings_dialog_import_message)
- .setNegativeButton(R.string.import_db) { _, _ ->
- dbImportLauncher.launch(arrayOf("application/json"))
- }
- .setPositiveButton(R.string.cancel) { _, _ ->
- scope.launch { snackbarHostState.showSnackbar(importCanceledMessage) }
- }
- .show()
- }
- )
-
if (databaseBackend == WalletDatabaseBackend.IndexedDB) SettingsItem(
title = stringResource(R.string.settings_migrate_db),
summary = stringResource(R.string.settings_migrate_db_summary),
@@ -346,12 +352,6 @@ fun SettingsContent(
onClick = model::offerDatabaseMigration,
)
- SettingsItem(
- title = stringResource(R.string.settings_version_app),
- summary = "${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR} ${BuildConfig.VERSION_CODE})",
- icon = ImageVector.vectorResource(R.drawable.ic_account_balance_wallet),
- )
-
SettingsItem(
title = stringResource(R.string.settings_version_core),
summary = "$walletVersion ($walletVersionHash)",
@@ -404,32 +404,32 @@ fun SettingsContent(
.show()
}
)
+ }
- pendingDbExport?.let { exportType ->
- AlertDialog(
- onDismissRequest = { pendingDbExport = null },
- title = { Text(stringResource(R.string.wallet_export_database)) },
- text = { Text(stringResource(R.string.wallet_export_database_warning)) },
- confirmButton = {
- Button(onClick = {
- pendingDbExport = null
- when (exportType) {
- DbExportType.Json ->
- dbExportLauncher.launch("taler-wallet-db-${System.currentTimeMillis()}.json")
- DbExportType.Raw ->
- rawDbExportLauncher.launch("taler-wallet-db-${System.currentTimeMillis()}.sqlite3")
- }
- }) {
- Text(stringResource(R.string.wallet_export_database_confirm))
- }
- },
- dismissButton = {
- TextButton(onClick = { pendingDbExport = null }) {
- Text(stringResource(R.string.cancel))
+ pendingDbExport?.let { exportType ->
+ AlertDialog(
+ onDismissRequest = { pendingDbExport = null },
+ title = { Text(stringResource(R.string.wallet_export_database)) },
+ text = { Text(stringResource(R.string.wallet_export_database_warning)) },
+ confirmButton = {
+ Button(onClick = {
+ pendingDbExport = null
+ when (exportType) {
+ DbExportType.Json ->
+ dbExportLauncher.launch("taler-wallet-db-${System.currentTimeMillis()}.json")
+ DbExportType.Raw ->
+ rawDbExportLauncher.launch("taler-wallet-db-${System.currentTimeMillis()}.sqlite3")
}
+ }) {
+ Text(stringResource(R.string.wallet_export_database_confirm))
}
- )
- }
+ },
+ dismissButton = {
+ TextButton(onClick = { pendingDbExport = null }) {
+ Text(stringResource(R.string.cancel))
+ }
+ }
+ )
}
BottomInsetsSpacer()
| ||||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-11-11 01:44 | bot-cg | New Issue | |
| 2026-11-11 01:44 | bot-cg | Relationship added | related to 0008536 |
| 2026-11-11 01:44 | bot-cg | File Added: before-android-1.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-android-2.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-ios-1.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-ios-2.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-ios-3.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-ios-4.png | |
| 2026-11-11 01:44 | bot-cg | File Added: before-web-1.png | |
| 2026-11-11 01:44 | bot-cg | File Added: after-android-1.png | |
| 2026-11-11 01:44 | bot-cg | File Added: after-android-2.png | |
| 2026-11-11 01:44 | bot-cg | File Added: android-F408-backup-and-version-visible.patch |