Refactor backup tasks

Base the backup tasks on UiBasedBackgroundTask
This commit is contained in:
Jakob Nixdorf 2021-02-06 16:18:16 +01:00
parent 7bf6cda6ed
commit 1d3f7af099
No known key found for this signature in database
GPG key ID: BE99BF86574A7DBC
7 changed files with 201 additions and 193 deletions

View file

@ -53,7 +53,10 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
import org.shadowice.flocke.andotp.Database.Entry; import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog; import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Tasks.BackupTask; import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
import org.shadowice.flocke.andotp.Utilities.BackupHelper; import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants; import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper; import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
@ -68,13 +71,10 @@ import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
public class BackupActivity extends BaseActivity public class BackupActivity extends BaseActivity {
implements BackupTask.BackupCallback {
private final static String TAG = BackupActivity.class.getSimpleName(); private final static String TAG = BackupActivity.class.getSimpleName();
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED; private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
@ -259,36 +259,18 @@ public class BackupActivity extends BaseActivity
pgpServiceConnection.unbindFromService(); pgpServiceConnection.unbindFromService();
} }
@Override private void handleBackupTaskResult(GenericBackupTask.BackupTaskResult result) {
public void onBackupFinished() { Toast.makeText(this, result.messageId, Toast.LENGTH_LONG).show();
hideProgress(); showBackupProgress(false);
} }
@Override private void showBackupProgress(boolean running) {
public void onBackupFailed() { btnBackup.setEnabled(!running);
hideProgress(); btnRestore.setEnabled(!running);
} chkOldFormat.setEnabled(!running);
swReplace.setEnabled(!running);
private void showProgress(boolean restore) { progressBackup.setVisibility(running ? View.VISIBLE : View.GONE);
btnBackup.setEnabled(false);
btnRestore.setEnabled(false);
chkOldFormat.setEnabled(false);
swReplace.setEnabled(false);
if (restore)
progressRestore.setVisibility(View.VISIBLE);
else
progressBackup.setVisibility(View.VISIBLE);
}
private void hideProgress() {
btnBackup.setEnabled(true);
btnRestore.setEnabled(true);
chkOldFormat.setEnabled(true);
swReplace.setEnabled(true);
progressRestore.setVisibility(View.GONE);
progressBackup.setVisibility(View.GONE);
} }
// Get the result from external activities // Get the result from external activities
@ -414,15 +396,11 @@ public class BackupActivity extends BaseActivity
if (Tools.isExternalStorageWritable()) { if (Tools.isExternalStorageWritable()) {
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey); ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
ExecutorService executor = Executors.newSingleThreadExecutor(); PlainTextBackupTask task = new PlainTextBackupTask(this, entries, uri);
task.setCallback(this::handleBackupTaskResult);
BackupTask backupTask = new BackupTask(this, Constants.BackupType.PLAIN_TEXT, DatabaseHelper.entriesToString(entries), this); task.execute();
showBackupProgress(true);
if (uri != null)
backupTask.setUri(uri);
showProgress(false);
executor.execute(backupTask);
} else { } else {
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
} }
@ -524,8 +502,13 @@ public class BackupActivity extends BaseActivity
private void doBackupCryptWithPassword(Uri uri, String password) { private void doBackupCryptWithPassword(Uri uri, String password) {
if (Tools.isExternalStorageWritable()) { if (Tools.isExternalStorageWritable()) {
showProgress(false); ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
BackupHelper.backupToFileAsync(this, uri, password, encryptionKey, this, false);
EncryptedBackupTask task = new EncryptedBackupTask(this, entries, password, uri);
task.setCallback(this::handleBackupTaskResult);
task.execute();
showBackupProgress(true);
} else { } else {
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
} }
@ -548,15 +531,11 @@ public class BackupActivity extends BaseActivity
private void doBackupEncrypted(Uri uri, String data) { private void doBackupEncrypted(Uri uri, String data) {
if (Tools.isExternalStorageWritable()) { if (Tools.isExternalStorageWritable()) {
ExecutorService executor = Executors.newSingleThreadExecutor(); PGPBackupTask task = new PGPBackupTask(this, data, uri);
task.setCallback(this::handleBackupTaskResult);
BackupTask backupTask = new BackupTask(this, Constants.BackupType.OPEN_PGP, data, this); task.execute();
showBackupProgress(true);
if (uri != null)
backupTask.setUri(uri);
showProgress(false);
executor.execute(backupTask);
} else { } else {
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
} }

View file

@ -1,124 +0,0 @@
package org.shadowice.flocke.andotp.Tasks;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
public class BackupTask implements Runnable {
final private Context context;
final private String payload;
final private Constants.BackupType type;
final private BackupCallback callback;
final private Handler handler;
private boolean silent = false;
private Uri uri = null;
private String password = null;
public BackupTask(Context context, Constants.BackupType type, String payload, BackupCallback callback) {
this.context = context;
this.payload = payload;
this.type = type;
this.callback = callback;
this.handler = new Handler(Looper.getMainLooper());
}
public void setUri(Uri uri) {
this.uri = uri;
}
public void setPassword(String password) {
this.password = password;
}
public void setSilent(boolean silent) {
this.silent = silent;
}
@Override
public void run() {
boolean success;
if (uri == null)
uri = getTargetUri();
if (uri == null)
return;
if (type == Constants.BackupType.PLAIN_TEXT) {
success = StorageAccessHelper.saveFile(context, uri, payload);
} else if (type == Constants.BackupType.ENCRYPTED) {
success = BackupHelper.backupToFile(context, uri, password, payload);
} else if (type == Constants.BackupType.OPEN_PGP) {
success = StorageAccessHelper.saveFile(context, uri, payload);
} else {
success = false;
}
if (success)
onFinished();
else
onFailed();
}
private Uri getTargetUri() {
Settings settings = new Settings(context);
BackupHelper.BackupFile backupFile = BackupHelper.backupFile(context, settings.getBackupLocation(), type);
if (backupFile.file != null) {
return backupFile.file.getUri();
} else {
showToast(context, backupFile.errorMessage);
return null;
}
}
private void showToast(Context context, int msgId) {
if (!this.silent) {
this.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, msgId, Toast.LENGTH_LONG).show();
}
});
}
}
private void onFinished() {
this.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();
if (callback != null)
callback.onBackupFinished();
}
});
}
private void onFailed() {
this.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.backup_toast_export_failed, Toast.LENGTH_LONG).show();
if (callback != null)
callback.onBackupFailed();
}
});
}
public interface BackupCallback {
void onBackupFinished();
void onBackupFailed();
}
}

View file

@ -0,0 +1,37 @@
package org.shadowice.flocke.andotp.Tasks;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
import java.util.ArrayList;
public class EncryptedBackupTask extends GenericBackupTask {
private final String password;
private final ArrayList<Entry> entries;
public EncryptedBackupTask(Context context, ArrayList<Entry> entries, String password, @Nullable Uri uri) {
super(context, uri);
this.entries = entries;
this.password = password;
}
@Override
@NonNull
protected Constants.BackupType getBackupType() {
return Constants.BackupType.ENCRYPTED;
}
@Override
protected boolean doBackup() {
String payload = DatabaseHelper.entriesToString(entries);
return BackupHelper.backupToFile(applicationContext, uri, password, payload);
}
}

View file

@ -0,0 +1,70 @@
package org.shadowice.flocke.andotp.Tasks;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.Settings;
public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBackupTask.BackupTaskResult> {
protected final Context applicationContext;
protected final Settings settings;
protected final Constants.BackupType type;
protected Uri uri;
public GenericBackupTask(Context context, @Nullable Uri uri) {
super(BackupTaskResult.failure());
this.applicationContext = context.getApplicationContext();
this.settings = new Settings(applicationContext);
this.type = getBackupType();
this.uri = uri;
}
@Override
@NonNull
protected BackupTaskResult doInBackground() {
if (uri == null) {
BackupHelper.BackupFile backupFile = BackupHelper.backupFile(applicationContext, settings.getBackupLocation(), type);
if (backupFile.file == null)
return new BackupTaskResult(backupFile.errorMessage);
uri = backupFile.file.getUri();
}
boolean success = doBackup();
if (success)
return BackupTaskResult.success();
else
return BackupTaskResult.failure();
}
@NonNull
protected abstract Constants.BackupType getBackupType();
protected abstract boolean doBackup();
public static class BackupTaskResult {
public final int messageId;
public BackupTaskResult(int messageId) {
this.messageId = messageId;
}
public static BackupTaskResult success() {
return new BackupTaskResult(R.string.backup_toast_export_success);
}
public static BackupTaskResult failure() {
return new BackupTaskResult(R.string.backup_toast_export_failed);
}
}
}

View file

@ -0,0 +1,30 @@
package org.shadowice.flocke.andotp.Tasks;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
public class PGPBackupTask extends GenericBackupTask {
private final String payload;
public PGPBackupTask(Context context, String payload, @Nullable Uri uri) {
super(context, uri);
this.payload = payload;
}
@Override
@NonNull
protected Constants.BackupType getBackupType() {
return Constants.BackupType.OPEN_PGP;
}
@Override
protected boolean doBackup() {
return StorageAccessHelper.saveFile(applicationContext, uri, payload);
}
}

View file

@ -0,0 +1,35 @@
package org.shadowice.flocke.andotp.Tasks;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
import java.util.ArrayList;
public class PlainTextBackupTask extends GenericBackupTask {
private final ArrayList<Entry> entries;
public PlainTextBackupTask(Context context, ArrayList<Entry> entries, @Nullable Uri uri) {
super(context, uri);
this.entries = entries;
}
@Override
@NonNull
protected Constants.BackupType getBackupType() {
return Constants.BackupType.PLAIN_TEXT;
}
@Override
protected boolean doBackup() {
String payload = DatabaseHelper.entriesToString(entries);
return StorageAccessHelper.saveFile(applicationContext, uri, payload);
}
}

View file

@ -7,13 +7,10 @@ import androidx.documentfile.provider.DocumentFile;
import org.shadowice.flocke.andotp.Database.Entry; import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Tasks.BackupTask;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
@ -104,22 +101,6 @@ public class BackupHelper {
return Constants.BackupType.UNAVAILABLE; return Constants.BackupType.UNAVAILABLE;
} }
public static void backupToFileAsync(Context context, Uri uri, String password, SecretKey encryptionKey, BackupTask.BackupCallback callback, boolean silent) {
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
ExecutorService executor = Executors.newSingleThreadExecutor();
BackupTask backupTask = new BackupTask(context, Constants.BackupType.ENCRYPTED, DatabaseHelper.entriesToString(entries), callback);
if (uri != null)
backupTask.setUri(uri);
backupTask.setPassword(password);
backupTask.setSilent(silent);
executor.execute(backupTask);
}
public static boolean backupToFile(Context context, Uri uri, String password, SecretKey encryptionKey) { public static boolean backupToFile(Context context, Uri uri, String password, SecretKey encryptionKey) {
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey); ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
String plain = DatabaseHelper.entriesToString(entries); String plain = DatabaseHelper.entriesToString(entries);