From 08c73922cc20b872437fc93750a5faa89dcb3860 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Wed, 29 Nov 2023 20:09:37 +0100 Subject: [PATCH] Explain vault backup permission error Users understandably get confused by the "No persisted URI permissions" error. This patch adds some text to the dialog explaining why this happened and how the user can fix the issue. This permission issue can happen for one of two reasons: - The user made a change to the backup destination (renamed, moved, deleted, etc) - Aegis was restored from an Android backup --- .../com/beemdevelopment/aegis/Preferences.java | 15 ++++++++++++--- .../beemdevelopment/aegis/ui/dialogs/Dialogs.java | 3 ++- .../aegis/vault/VaultBackupManager.java | 9 +++++---- .../vault/VaultBackupPermissionException.java | 7 +++++++ app/src/main/res/values/strings.xml | 5 +++++ 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupPermissionException.java diff --git a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java index 3bf8d965..29ec0756 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java +++ b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import com.beemdevelopment.aegis.util.JsonUtils; import com.beemdevelopment.aegis.util.TimeUtils; +import com.beemdevelopment.aegis.vault.VaultBackupPermissionException; import org.json.JSONArray; import org.json.JSONException; @@ -507,14 +508,16 @@ public class Preferences { private final Date _time; private boolean _isBuiltIn; private final String _error; + private final boolean _isPermissionError; public BackupResult(@Nullable Exception e) { - this(new Date(), e == null ? null : e.toString()); + this(new Date(), e == null ? null : e.toString(), e instanceof VaultBackupPermissionException); } - private BackupResult(Date time, @Nullable String error) { + private BackupResult(Date time, @Nullable String error, boolean isPermissionError) { _time = time; _error = error; + _isPermissionError = isPermissionError; } @Nullable @@ -542,12 +545,17 @@ public class Preferences { _isBuiltIn = isBuiltIn; } + public boolean isPermissionError() { + return _isPermissionError; + } + public String toJson() { JSONObject obj = new JSONObject(); try { obj.put("time", _time.getTime()); obj.put("error", _error == null ? JSONObject.NULL : _error); + obj.put("isPermissionError", _isPermissionError); } catch (JSONException e) { throw new RuntimeException(e); } @@ -559,7 +567,8 @@ public class Preferences { JSONObject obj = new JSONObject(json); long time = obj.getLong("time"); String error = JsonUtils.optString(obj, "error"); - return new BackupResult(new Date(time), error); + boolean isPermissionError = obj.optBoolean("isPermissionError"); + return new BackupResult(new Date(time), error, isPermissionError); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java b/app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java index 1dd7c873..8e0bbb51 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java @@ -407,7 +407,8 @@ public class Dialogs { public static void showBackupErrorDialog(Context context, Preferences.BackupResult backupRes, DialogInterface.OnClickListener listener) { String system = context.getString(backupRes.isBuiltIn() ? R.string.backup_system_builtin : R.string.backup_system_android); - String message = context.getString(R.string.backup_error_dialog_details, system, backupRes.getElapsedSince(context)); + @StringRes int details = backupRes.isPermissionError() ? R.string.backup_permission_error_dialog_details : R.string.backup_error_dialog_details; + String message = context.getString(details, system, backupRes.getElapsedSince(context)); Dialogs.showErrorDialog(context, message, backupRes.getError(), listener); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java index 47d16523..48711626 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java @@ -53,14 +53,15 @@ public class VaultBackupManager { try { createBackup(tempFile, dirUri, versionsToKeep); _prefs.setBuiltInBackupResult(new Preferences.BackupResult(null)); - } catch (VaultRepositoryException e) { + } catch (VaultRepositoryException | VaultBackupPermissionException e) { e.printStackTrace(); _prefs.setBuiltInBackupResult(new Preferences.BackupResult(e)); } }); } - private void createBackup(File tempFile, Uri dirUri, int versionsToKeep) throws VaultRepositoryException { + private void createBackup(File tempFile, Uri dirUri, int versionsToKeep) + throws VaultRepositoryException, VaultBackupPermissionException { FileInfo fileInfo = new FileInfo(FILENAME_PREFIX); DocumentFile dir = DocumentFile.fromTreeUri(_context, dirUri); @@ -68,7 +69,7 @@ public class VaultBackupManager { Log.i(TAG, String.format("Creating backup at %s: %s", Uri.decode(dir.getUri().toString()), fileInfo.toString())); if (!hasPermissionsAt(dirUri)) { - throw new VaultRepositoryException("No persisted URI permissions"); + throw new VaultBackupPermissionException("No persisted URI permissions"); } // If we create a file with a name that already exists, SAF will append a number @@ -92,7 +93,7 @@ public class VaultBackupManager { } catch (IOException e) { throw new VaultRepositoryException(e); } - } catch (VaultRepositoryException e) { + } catch (VaultRepositoryException | VaultBackupPermissionException e) { Log.e(TAG, String.format("Unable to create backup: %s", e.toString())); throw e; } finally { diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupPermissionException.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupPermissionException.java new file mode 100644 index 00000000..93e91daa --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupPermissionException.java @@ -0,0 +1,7 @@ +package com.beemdevelopment.aegis.vault; + +public class VaultBackupPermissionException extends Exception { + public VaultBackupPermissionException(String message) { + super(message); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aa5b2954..ebeac9a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -390,6 +390,11 @@ comment="The first parameter is the type of backup (e.g. built-in or Android backup). The second parameter is an elapsed time in the style of 'x seconds/minutes/days ago'."> A recent vault backup attempt using %s failed because an error occurred. The backup was attempted %s. Please check your backup settings to make sure backups can complete successfully. + + A recent vault backup attempt using %s failed because Aegis did not have permission to write to the backup destination. The backup was attempted %s. This error can occur if you moved/renamed the backup destination or if you recently restored Aegis from a backup. Please reconfigure the backup destination. + Aegis\' built-in automatic backups Android\'s cloud backup system