Use only one TaskFragment in the BackupActivity
This commit is contained in:
parent
2bec1e8224
commit
1b4df88916
3 changed files with 89 additions and 95 deletions
|
@ -64,6 +64,7 @@ import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PlainTextRestoreTask;
|
import org.shadowice.flocke.andotp.Tasks.PlainTextRestoreTask;
|
||||||
|
import org.shadowice.flocke.andotp.Tasks.UiBasedBackgroundTask;
|
||||||
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;
|
||||||
|
@ -81,8 +82,7 @@ import javax.crypto.SecretKey;
|
||||||
public class BackupActivity extends BaseActivity {
|
public class BackupActivity extends BaseActivity {
|
||||||
private final static String TAG = BackupActivity.class.getSimpleName();
|
private final static String TAG = BackupActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final String TAG_BACKUP_TASK_FRAGMENT = "BackupActivity.BackupTaskFragmentTag";
|
private static final String TAG_TASK_FRAGMENT = "BackupActivity.TaskFragment";
|
||||||
private static final String TAG_RESTORE_TASK_FRAGMENT = "BackupActivity.RestoreTaskFragmentTag";
|
|
||||||
|
|
||||||
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
||||||
private SecretKey encryptionKey = null;
|
private SecretKey encryptionKey = null;
|
||||||
|
@ -286,10 +286,11 @@ public class BackupActivity extends BaseActivity {
|
||||||
notifyBackupState(R.string.backup_toast_export_failed);
|
notifyBackupState(R.string.backup_toast_export_failed);
|
||||||
|
|
||||||
// Clean up the task fragment
|
// Clean up the task fragment
|
||||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
if (backupTaskFragment != null) {
|
|
||||||
|
if (taskFragment != null && taskFragment.isEmpty()) {
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
.remove(backupTaskFragment)
|
.remove(taskFragment)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,10 +321,10 @@ public class BackupActivity extends BaseActivity {
|
||||||
showRestoreProgress(false);
|
showRestoreProgress(false);
|
||||||
|
|
||||||
// Clean up the task fragment
|
// Clean up the task fragment
|
||||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
if (restoreTaskFragment != null) {
|
if (taskFragment != null && taskFragment.isEmpty()) {
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
.remove(restoreTaskFragment)
|
.remove(taskFragment)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +608,7 @@ public class BackupActivity extends BaseActivity {
|
||||||
if (settings.getOpenPGPVerify()) {
|
if (settings.getOpenPGPVerify()) {
|
||||||
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
|
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
|
||||||
|
|
||||||
if (sigResult.getResult() == OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED) {
|
if (sigResult != null && sigResult.getResult() == OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED) {
|
||||||
restoreEntries(outputStreamToString(os), true);
|
restoreEntries(outputStreamToString(os), true);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_openpgp_not_verified, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_openpgp_not_verified, Toast.LENGTH_LONG).show();
|
||||||
|
@ -620,6 +621,10 @@ public class BackupActivity extends BaseActivity {
|
||||||
} else if (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) == OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED) {
|
} else if (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) == OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED) {
|
||||||
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||||
|
|
||||||
|
// Can't do anything without this intent
|
||||||
|
if (pi == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Small hack to keep the target file even after user interaction
|
// Small hack to keep the target file even after user interaction
|
||||||
if (requestCode == Constants.INTENT_BACKUP_ENCRYPT_PGP) {
|
if (requestCode == Constants.INTENT_BACKUP_ENCRYPT_PGP) {
|
||||||
encryptTargetFile = file;
|
encryptTargetFile = file;
|
||||||
|
@ -634,89 +639,70 @@ public class BackupActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
} else if (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) == OpenPgpApi.RESULT_CODE_ERROR) {
|
} else if (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) == OpenPgpApi.RESULT_CODE_ERROR) {
|
||||||
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
|
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
|
||||||
Toast.makeText(this, String.format(getString(R.string.backup_toast_openpgp_error), error.getMessage()), Toast.LENGTH_LONG).show();
|
|
||||||
|
if (error != null)
|
||||||
|
Toast.makeText(this, String.format(getString(R.string.backup_toast_openpgp_error), error.getMessage()), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private BackupTaskFragment findBackupTaskFragment() {
|
private TaskFragment findTaskFragment() {
|
||||||
return (BackupTaskFragment) getFragmentManager().findFragmentByTag(TAG_BACKUP_TASK_FRAGMENT);
|
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private RestoreTaskFragment findRestoreTaskFragment() {
|
|
||||||
return (RestoreTaskFragment) getFragmentManager().findFragmentByTag(TAG_RESTORE_TASK_FRAGMENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startBackupTask(GenericBackupTask task) {
|
private void startBackupTask(GenericBackupTask task) {
|
||||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
|
||||||
|
|
||||||
// Don't start a task if we already have an active task running (backup or restore).
|
// Don't start a task if we already have an active task running (backup or restore).
|
||||||
if ((backupTaskFragment == null || backupTaskFragment.task.isCanceled()) && (restoreTaskFragment == null || restoreTaskFragment.task.isCanceled())) {
|
if (taskFragment == null || taskFragment.isEmpty()) {
|
||||||
if (backupTaskFragment == null) {
|
if (taskFragment == null) {
|
||||||
backupTaskFragment = new BackupTaskFragment();
|
taskFragment = new TaskFragment();
|
||||||
getFragmentManager()
|
getFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.add(backupTaskFragment, TAG_BACKUP_TASK_FRAGMENT)
|
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
backupTaskFragment.startTask(task);
|
taskFragment.startBackupTask(task);
|
||||||
|
|
||||||
showBackupProgress(true);
|
showBackupProgress(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startRestoreTask(GenericRestoreTask task) {
|
private void startRestoreTask(GenericRestoreTask task) {
|
||||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
|
||||||
|
|
||||||
// Don't start a task if we already have an active task running (backup or restore).
|
// Don't start a task if we already have an active task running (backup or restore).
|
||||||
if ((backupTaskFragment == null || backupTaskFragment.task.isCanceled()) && (restoreTaskFragment == null || restoreTaskFragment.task.isCanceled())) {
|
if (taskFragment == null || taskFragment.isEmpty()) {
|
||||||
if (restoreTaskFragment == null) {
|
if (taskFragment == null) {
|
||||||
restoreTaskFragment = new RestoreTaskFragment();
|
taskFragment = new TaskFragment();
|
||||||
getFragmentManager()
|
getFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.add(restoreTaskFragment, TAG_RESTORE_TASK_FRAGMENT)
|
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreTaskFragment.startTask(task);
|
taskFragment.startRestoreTask(task);
|
||||||
|
|
||||||
showRestoreProgress(true);
|
showRestoreProgress(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBackgroundBackupTask() {
|
private void checkBackgroundTask() {
|
||||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
|
|
||||||
if (backupTaskFragment != null) {
|
if (taskFragment != null) {
|
||||||
if (backupTaskFragment.task.isCanceled()) {
|
if (taskFragment.isEmpty()) {
|
||||||
// The task was canceled or has finished, so remove the task fragment.
|
// The task was canceled or has finished, so remove the task fragment.
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
.remove(backupTaskFragment)
|
.remove(taskFragment)
|
||||||
.commit();
|
.commit();
|
||||||
} else {
|
} else {
|
||||||
backupTaskFragment.task.setCallback(this::handleBackupTaskResult);
|
if (taskFragment.isRestoreRunning())
|
||||||
showBackupProgress(true);
|
showRestoreProgress(true);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (taskFragment.isBackupRunning())
|
||||||
|
showBackupProgress(true);
|
||||||
|
|
||||||
private void checkBackgroundRestoreTask() {
|
taskFragment.setCallbacks(this::handleBackupTaskResult, this::handleRestoreTaskResult);
|
||||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
|
||||||
|
|
||||||
if (restoreTaskFragment != null) {
|
|
||||||
if (restoreTaskFragment.task.isCanceled()) {
|
|
||||||
// The task was canceled or has finished, so remove the task fragment.
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(restoreTaskFragment)
|
|
||||||
.commit();
|
|
||||||
} else {
|
|
||||||
restoreTaskFragment.task.setCallback(this::handleRestoreTaskResult);
|
|
||||||
showRestoreProgress(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,22 +712,16 @@ public class BackupActivity extends BaseActivity {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
||||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
TaskFragment taskFragment = findTaskFragment();
|
||||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
|
||||||
|
|
||||||
if (backupTaskFragment != null)
|
if (taskFragment != null)
|
||||||
backupTaskFragment.task.setCallback(null);
|
taskFragment.setCallbacks(null, null);
|
||||||
|
|
||||||
if (restoreTaskFragment != null)
|
|
||||||
restoreTaskFragment.task.setCallback(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
checkBackgroundTask();
|
||||||
checkBackgroundBackupTask();
|
|
||||||
checkBackgroundRestoreTask();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -749,33 +729,43 @@ public class BackupActivity extends BaseActivity {
|
||||||
return allowExit; // Don't destroy the backup activity as long as a backup task is running
|
return allowExit; // Don't destroy the backup activity as long as a backup task is running
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retained instance fragment to hold a running {@link GenericBackupTask} between configuration changes.*/
|
public static class TaskFragment extends Fragment {
|
||||||
public static class BackupTaskFragment extends Fragment {
|
GenericBackupTask backupTask;
|
||||||
GenericBackupTask task;
|
GenericRestoreTask restoreTask;
|
||||||
|
|
||||||
public BackupTaskFragment() {
|
public TaskFragment() {
|
||||||
super();
|
super();
|
||||||
setRetainInstance(true);
|
setRetainInstance(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startTask(@NonNull GenericBackupTask task) {
|
public void setCallbacks(UiBasedBackgroundTask.UiCallback<GenericBackupTask.BackupTaskResult> backupCallback, UiBasedBackgroundTask.UiCallback<GenericRestoreTask.RestoreTaskResult> restoreCallback) {
|
||||||
this.task = task;
|
if (backupTask != null && backupTask.isRunning())
|
||||||
this.task.execute();
|
backupTask.setCallback(backupCallback);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retained instance fragment to hold a running {@link GenericRestoreTask} between configuration changes.*/
|
if (restoreTask != null && restoreTask.isRunning())
|
||||||
public static class RestoreTaskFragment extends Fragment {
|
restoreTask.setCallback(restoreCallback);
|
||||||
GenericRestoreTask task;
|
|
||||||
|
|
||||||
public RestoreTaskFragment() {
|
|
||||||
super();
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startTask(@NonNull GenericRestoreTask task) {
|
public boolean isEmpty() {
|
||||||
this.task = task;
|
return ((backupTask == null || !backupTask.isRunning()) && (restoreTask == null || !restoreTask.isRunning()));
|
||||||
this.task.execute();
|
}
|
||||||
|
|
||||||
|
public boolean isRestoreRunning() {
|
||||||
|
return (restoreTask != null && restoreTask.isRunning());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBackupRunning() {
|
||||||
|
return (backupTask != null && backupTask.isRunning());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startBackupTask(@NonNull GenericBackupTask task) {
|
||||||
|
this.backupTask = task;
|
||||||
|
this.backupTask.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startRestoreTask(@NonNull GenericRestoreTask task) {
|
||||||
|
this.restoreTask = task;
|
||||||
|
this.restoreTask.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -121,14 +120,6 @@ public class SettingsActivity extends BaseActivity
|
||||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home && !canGoBack)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
@ -150,7 +141,9 @@ public class SettingsActivity extends BaseActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onSupportNavigateUp() {
|
public boolean onSupportNavigateUp() {
|
||||||
finishWithResult();
|
if (canGoBack)
|
||||||
|
finishWithResult();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
private Result awaitedResult;
|
private Result awaitedResult;
|
||||||
|
|
||||||
private volatile boolean isCanceled = false;
|
private volatile boolean isCanceled = false;
|
||||||
|
private volatile boolean isRunning = false;
|
||||||
|
|
||||||
/** @param failedResult The result to return if the task fails (throws an exception or returns null). */
|
/** @param failedResult The result to return if the task fails (throws an exception or returns null). */
|
||||||
public UiBasedBackgroundTask(@NonNull Result failedResult) {
|
public UiBasedBackgroundTask(@NonNull Result failedResult) {
|
||||||
|
@ -52,7 +53,10 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitResultOnMainThread(@NonNull UiCallback<Result> callback, @NonNull Result result) {
|
private void emitResultOnMainThread(@NonNull UiCallback<Result> callback, @NonNull Result result) {
|
||||||
mainThreadHandler.post(() -> callback.onResult(result));
|
mainThreadHandler.post(() -> {
|
||||||
|
callback.onResult(result);
|
||||||
|
isRunning = false;
|
||||||
|
});
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
this.awaitedResult = null;
|
this.awaitedResult = null;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +64,7 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
/** Executed the task on a background thread. Safe to call from the main thread. */
|
/** Executed the task on a background thread. Safe to call from the main thread. */
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public void execute() {
|
public void execute() {
|
||||||
|
isRunning = true;
|
||||||
executor.execute(this::runTask);
|
executor.execute(this::runTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +101,15 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
return isCanceled;
|
return isCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AnyThread
|
||||||
|
public boolean isRunning() {
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
isCanceled = true;
|
isCanceled = true;
|
||||||
|
isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
Loading…
Reference in a new issue