Create generic activity class to simplify handling background tasks
This commit is contained in:
parent
1b4df88916
commit
faa8fb3774
14 changed files with 333 additions and 472 deletions
|
@ -22,19 +22,13 @@
|
|||
|
||||
package org.shadowice.flocke.andotp.Activities;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
|
@ -59,17 +53,14 @@ import org.shadowice.flocke.andotp.View.AutoFillable.AutoFillableTextInputEditTe
|
|||
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
|
||||
public class AuthenticateActivity extends BaseActivity
|
||||
public class AuthenticateActivity extends BackgroundTaskActivity<AuthenticationTask.Result>
|
||||
implements EditText.OnEditorActionListener, View.OnClickListener {
|
||||
private final AutoFillableTextInputEditText.AutoFillTextListener autoFillTextListener = text -> startAuthTask(text.toString());
|
||||
|
||||
private static final String TAG_TASK_FRAGMENT = "AuthenticateActivity.TaskFragmentTag";
|
||||
|
||||
private AuthMethod authMethod;
|
||||
private String newEncryption = "";
|
||||
private String existingAuthCredentials;
|
||||
private boolean isAuthUpgrade = false;
|
||||
private ProcessLifecycleObserver observer;
|
||||
|
||||
private TextInputLayout passwordLayout;
|
||||
AutoFillableTextInputEditText passwordInput;
|
||||
|
@ -113,10 +104,6 @@ public class AuthenticateActivity extends BaseActivity
|
|||
}
|
||||
});
|
||||
|
||||
observer = new ProcessLifecycleObserver();
|
||||
ProcessLifecycleOwner.get().getLifecycle()
|
||||
.addObserver(observer);
|
||||
|
||||
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
||||
}
|
||||
|
||||
|
@ -171,58 +158,21 @@ public class AuthenticateActivity extends BaseActivity
|
|||
unlockProgress = v.findViewById(R.id.unlockProgress);
|
||||
}
|
||||
|
||||
private void cancelBackgroundTask() {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
taskFragment.task.cancel();
|
||||
}
|
||||
setupUiForTaskState(false);
|
||||
}
|
||||
|
||||
private class ProcessLifecycleObserver implements DefaultLifecycleObserver {
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner) {
|
||||
if (settings.getRelockOnBackground()) {
|
||||
cancelBackgroundTask();
|
||||
}
|
||||
}
|
||||
protected boolean cancelTaskOnScreenOff() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkBackgroundTask();
|
||||
}
|
||||
|
||||
private void checkBackgroundTask() {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.task.isCanceled()) {
|
||||
// The task was canceled, so remove the task fragment and reset password input.
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
resetPasswordInput();
|
||||
} else {
|
||||
taskFragment.task.setCallback(this::handleResult);
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetPasswordInput() {
|
||||
protected void onReturnToCanceledTask() {
|
||||
passwordInput.setText("");
|
||||
passwordInput.requestFocus();
|
||||
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
keyboard.showSoftInput(passwordInput, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TaskFragment findTaskFragment() {
|
||||
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||
}
|
||||
|
||||
private void setupUiForTaskState(boolean isTaskRunning) {
|
||||
@Override
|
||||
protected void setupUiForTaskState(boolean isTaskRunning) {
|
||||
passwordLayout.setEnabled(!isTaskRunning);
|
||||
passwordInput.setEnabled(!isTaskRunning);
|
||||
unlockButton.setEnabled(!isTaskRunning);
|
||||
|
@ -246,25 +196,12 @@ public class AuthenticateActivity extends BaseActivity
|
|||
}
|
||||
|
||||
private void startAuthTask(String plainPassword) {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
// Don't start a task if we already have an active task running.
|
||||
if (taskFragment == null || taskFragment.task.isCanceled()) {
|
||||
AuthenticationTask task = new AuthenticationTask(this, isAuthUpgrade, existingAuthCredentials, plainPassword);
|
||||
task.setCallback(this::handleResult);
|
||||
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new TaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
taskFragment.startTask(task);
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
startBackgroundTask(task);
|
||||
}
|
||||
|
||||
private void handleResult(Result result) {
|
||||
@Override
|
||||
void onTaskResult(Result result) {
|
||||
if (result.authUpgradeFailed) {
|
||||
Toast.makeText(this, R.string.settings_toast_auth_upgrade_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -296,47 +233,14 @@ public class AuthenticateActivity extends BaseActivity
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
taskFragment.task.setCallback(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
passwordInput.setAutoFillTextListener(null);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
ProcessLifecycleOwner.get().getLifecycle()
|
||||
.removeObserver(observer);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldDestroyOnScreenOff() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Retained instance fragment to hold a running {@link AuthenticationTask} between configuration changes.*/
|
||||
public static class TaskFragment extends Fragment {
|
||||
|
||||
AuthenticationTask task;
|
||||
|
||||
public TaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void startTask(@NonNull AuthenticationTask task) {
|
||||
this.task = task;
|
||||
task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
package org.shadowice.flocke.andotp.Activities;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
|
||||
import org.shadowice.flocke.andotp.Tasks.UiBasedBackgroundTask;
|
||||
|
||||
public abstract class BackgroundTaskActivity<Result> extends BaseActivity {
|
||||
final protected String TAG_TASK_FRAGMENT = this.getClass().getSimpleName() + ".TaskFragment";
|
||||
|
||||
private ProcessLifecycleObserver observer = null;
|
||||
|
||||
abstract void onTaskResult(Result result);
|
||||
|
||||
protected void onReturnToCanceledTask() {
|
||||
// This can be overwritten if we need to do something here
|
||||
}
|
||||
|
||||
protected void setupUiForTaskState(boolean running) {
|
||||
// This can be overwritten when we need to give some UI feedback
|
||||
}
|
||||
|
||||
protected boolean cancelTaskOnScreenOff() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (cancelTaskOnScreenOff()) {
|
||||
observer = new ProcessLifecycleObserver();
|
||||
|
||||
ProcessLifecycleOwner.get().getLifecycle()
|
||||
.addObserver(observer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (observer != null) {
|
||||
ProcessLifecycleOwner.get().getLifecycle()
|
||||
.removeObserver(observer);
|
||||
|
||||
observer = null;
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkBackgroundTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null)
|
||||
taskFragment.setCallback(null);
|
||||
}
|
||||
|
||||
protected void cancelBackgroundTask() {
|
||||
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null)
|
||||
taskFragment.cancelTask();
|
||||
|
||||
setupUiForTaskState(false);
|
||||
}
|
||||
|
||||
protected void startBackgroundTask(UiBasedBackgroundTask<Result> task) {
|
||||
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||
|
||||
// Don't start a task if we already have an active task running.
|
||||
if (taskFragment == null || taskFragment.isCanceled()) {
|
||||
task.setCallback(this::handleTaskResult);
|
||||
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new TaskFragment<>();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
|
||||
taskFragment.startTask(task);
|
||||
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTaskResult(Result result) {
|
||||
setupUiForTaskState(false);
|
||||
|
||||
onTaskResult(result);
|
||||
|
||||
// Remove the task fragment after the task is finished
|
||||
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBackgroundTask() {
|
||||
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.isCanceled()) {
|
||||
// The task was canceled, so remove the task fragment
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
|
||||
onReturnToCanceledTask();
|
||||
|
||||
setupUiForTaskState(false);
|
||||
} else {
|
||||
taskFragment.setCallback(this::handleTaskResult);
|
||||
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
} else {
|
||||
setupUiForTaskState(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
private TaskFragment<Result> findTaskFragment() {
|
||||
Fragment fragment = getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||
|
||||
if (fragment instanceof TaskFragment)
|
||||
return (TaskFragment<Result>) fragment;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private class ProcessLifecycleObserver implements DefaultLifecycleObserver {
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner) {
|
||||
if (cancelTaskOnScreenOff())
|
||||
cancelBackgroundTask();
|
||||
}
|
||||
}
|
||||
|
||||
public static class TaskFragment<Result> extends Fragment {
|
||||
private UiBasedBackgroundTask<Result> task;
|
||||
|
||||
public TaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void startTask(@NonNull UiBasedBackgroundTask<Result> task) {
|
||||
this.task = task;
|
||||
task.execute();
|
||||
}
|
||||
|
||||
public void setCallback(@Nullable UiBasedBackgroundTask.UiCallback<Result> callback) {
|
||||
if (this.task != null)
|
||||
this.task.setCallback(callback);
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
if (task != null)
|
||||
return task.isCanceled();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
public void cancelTask() {
|
||||
if (task != null)
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
package org.shadowice.flocke.andotp.Activities;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
|
@ -31,8 +30,6 @@ import android.content.IntentSender;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
@ -56,10 +53,9 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
|||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||
|
@ -79,11 +75,9 @@ import java.util.ArrayList;
|
|||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class BackupActivity extends BaseActivity {
|
||||
public class BackupActivity extends BackgroundTaskActivity<BackupTaskResult> {
|
||||
private final static String TAG = BackupActivity.class.getSimpleName();
|
||||
|
||||
private static final String TAG_TASK_FRAGMENT = "BackupActivity.TaskFragment";
|
||||
|
||||
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
||||
private SecretKey encryptionKey = null;
|
||||
|
||||
|
@ -105,6 +99,8 @@ public class BackupActivity extends BaseActivity {
|
|||
private boolean reload = false;
|
||||
private boolean allowExit = true;
|
||||
|
||||
private BackupTaskResult.ResultType currentTask = BackupTaskResult.ResultType.NONE;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -276,29 +272,28 @@ public class BackupActivity extends BaseActivity {
|
|||
Toast.makeText(this, msgId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void handleBackupTaskResult(GenericBackupTask.BackupTaskResult result) {
|
||||
showBackupProgress(false);
|
||||
@Override
|
||||
void onTaskResult(BackupTaskResult backupTaskResult) {
|
||||
if (backupTaskResult.resultType == BackupTaskResult.ResultType.BACKUP)
|
||||
handleBackupTaskResult(backupTaskResult);
|
||||
else if (backupTaskResult.resultType == BackupTaskResult.ResultType.RESTORE)
|
||||
handleRestoreTaskResult(backupTaskResult);
|
||||
}
|
||||
|
||||
private void handleBackupTaskResult(BackupTaskResult result) {
|
||||
if (result.messageId != 0)
|
||||
notifyBackupState(result.messageId);
|
||||
else
|
||||
if (!result.success)
|
||||
if (result.success)
|
||||
notifyBackupState(R.string.backup_toast_export_success);
|
||||
else
|
||||
notifyBackupState(R.string.backup_toast_export_failed);
|
||||
|
||||
// Clean up the task fragment
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null && taskFragment.isEmpty()) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
if (result.success)
|
||||
finishWithResult();
|
||||
}
|
||||
|
||||
private void handleRestoreTaskResult(GenericRestoreTask.RestoreTaskResult result) {
|
||||
private void handleRestoreTaskResult(BackupTaskResult result) {
|
||||
if (result.success) {
|
||||
if (result.isPGP) {
|
||||
InputStream is = new ByteArrayInputStream(result.payload.getBytes(StandardCharsets.UTF_8));
|
||||
|
@ -318,20 +313,23 @@ public class BackupActivity extends BaseActivity {
|
|||
notifyBackupState(R.string.backup_toast_import_failed);
|
||||
}
|
||||
|
||||
showRestoreProgress(false);
|
||||
|
||||
// Clean up the task fragment
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null && taskFragment.isEmpty()) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
if (result.success && !result.isPGP)
|
||||
finishWithResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupUiForTaskState(boolean running) {
|
||||
if (currentTask == BackupTaskResult.ResultType.BACKUP)
|
||||
showBackupProgress(running);
|
||||
else if (currentTask == BackupTaskResult.ResultType.RESTORE)
|
||||
showRestoreProgress(running);
|
||||
}
|
||||
|
||||
protected void startBackgroundTask(UiBasedBackgroundTask<BackupTaskResult> task, BackupTaskResult.ResultType type) {
|
||||
currentTask = type;
|
||||
startBackgroundTask(task);
|
||||
}
|
||||
|
||||
private void toggleInProgressMode(boolean running) {
|
||||
allowExit = !running;
|
||||
|
||||
|
@ -465,9 +463,7 @@ public class BackupActivity extends BaseActivity {
|
|||
private void doRestorePlain(Uri uri) {
|
||||
if (Tools.isExternalStorageReadable()) {
|
||||
PlainTextRestoreTask task = new PlainTextRestoreTask(this, uri);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
startRestoreTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -478,9 +474,7 @@ public class BackupActivity extends BaseActivity {
|
|||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
||||
|
||||
PlainTextBackupTask task = new PlainTextBackupTask(this, entries, uri);
|
||||
task.setCallback(this::handleBackupTaskResult);
|
||||
|
||||
startBackupTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -514,9 +508,7 @@ public class BackupActivity extends BaseActivity {
|
|||
private void doRestoreCryptWithPassword(Uri uri, String password, boolean old_format) {
|
||||
if (Tools.isExternalStorageReadable()) {
|
||||
EncryptedRestoreTask task = new EncryptedRestoreTask(this, uri, password, old_format);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
startRestoreTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -538,9 +530,7 @@ public class BackupActivity extends BaseActivity {
|
|||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
||||
|
||||
EncryptedBackupTask task = new EncryptedBackupTask(this, entries, password, uri);
|
||||
task.setCallback(this::handleBackupTaskResult);
|
||||
|
||||
startBackupTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -553,17 +543,13 @@ public class BackupActivity extends BaseActivity {
|
|||
decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
|
||||
PGPRestoreTask task = new PGPRestoreTask(this, uri, decryptIntent);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
startRestoreTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||
}
|
||||
|
||||
private void doBackupEncrypted(Uri uri, String data) {
|
||||
if (Tools.isExternalStorageWritable()) {
|
||||
PGPBackupTask task = new PGPBackupTask(this, data, uri);
|
||||
task.setCallback(this::handleBackupTaskResult);
|
||||
|
||||
startBackupTask(task);
|
||||
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -645,127 +631,8 @@ public class BackupActivity extends BaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TaskFragment findTaskFragment() {
|
||||
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||
}
|
||||
|
||||
private void startBackupTask(GenericBackupTask task) {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
// Don't start a task if we already have an active task running (backup or restore).
|
||||
if (taskFragment == null || taskFragment.isEmpty()) {
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new TaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
|
||||
taskFragment.startBackupTask(task);
|
||||
showBackupProgress(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void startRestoreTask(GenericRestoreTask task) {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
// Don't start a task if we already have an active task running (backup or restore).
|
||||
if (taskFragment == null || taskFragment.isEmpty()) {
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new TaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
|
||||
taskFragment.startRestoreTask(task);
|
||||
showRestoreProgress(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBackgroundTask() {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.isEmpty()) {
|
||||
// The task was canceled or has finished, so remove the task fragment.
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
} else {
|
||||
if (taskFragment.isRestoreRunning())
|
||||
showRestoreProgress(true);
|
||||
|
||||
if (taskFragment.isBackupRunning())
|
||||
showBackupProgress(true);
|
||||
|
||||
taskFragment.setCallbacks(this::handleBackupTaskResult, this::handleRestoreTaskResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null)
|
||||
taskFragment.setCallbacks(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkBackgroundTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldDestroyOnScreenOff() {
|
||||
return allowExit; // Don't destroy the backup activity as long as a backup task is running
|
||||
}
|
||||
|
||||
public static class TaskFragment extends Fragment {
|
||||
GenericBackupTask backupTask;
|
||||
GenericRestoreTask restoreTask;
|
||||
|
||||
public TaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void setCallbacks(UiBasedBackgroundTask.UiCallback<GenericBackupTask.BackupTaskResult> backupCallback, UiBasedBackgroundTask.UiCallback<GenericRestoreTask.RestoreTaskResult> restoreCallback) {
|
||||
if (backupTask != null && backupTask.isRunning())
|
||||
backupTask.setCallback(backupCallback);
|
||||
|
||||
if (restoreTask != null && restoreTask.isRunning())
|
||||
restoreTask.setCallback(restoreCallback);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return ((backupTask == null || !backupTask.isRunning()) && (restoreTask == null || !restoreTask.isRunning()));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
package org.shadowice.flocke.andotp.Activities;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.backup.BackupManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
|
@ -39,13 +38,14 @@ import android.preference.PreferenceFragment;
|
|||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import android.provider.DocumentsContract;
|
||||
import android.util.Log;
|
||||
import android.view.ViewStub;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpAppPreference;
|
||||
import org.openintents.openpgp.util.OpenPgpKeyPreference;
|
||||
|
@ -67,18 +67,16 @@ import javax.crypto.SecretKey;
|
|||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||
|
||||
public class SettingsActivity extends BaseActivity
|
||||
public class SettingsActivity extends BackgroundTaskActivity<ChangeEncryptionTask.Result>
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener, EncryptionHelper.EncryptionChangeCallback {
|
||||
|
||||
private static final String TAG_TASK_FRAGMENT = "SettingsActivity.TaskFragmentTag";
|
||||
|
||||
private SettingsFragment fragment;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
private SecretKey encryptionKey = null;
|
||||
private boolean encryptionChanged = false;
|
||||
|
||||
private Toast inProgress = null;
|
||||
private Snackbar inProgress = null;
|
||||
private boolean canGoBack = true;
|
||||
|
||||
@Override
|
||||
|
@ -189,7 +187,7 @@ public class SettingsActivity extends BaseActivity
|
|||
(settings.getAndroidBackupServiceEnabled() ? "enabled" : "disabled"));
|
||||
|
||||
int message = settings.getAndroidBackupServiceEnabled() ? R.string.settings_toast_android_sync_enabled : R.string.settings_toast_android_sync_disabled;
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
Snackbar.make(fragment.getView(), message, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
fragment.updateAutoBackup();
|
||||
|
@ -218,104 +216,41 @@ public class SettingsActivity extends BaseActivity
|
|||
fragment.setEncryptionKey(newEncryptionKey);
|
||||
}
|
||||
|
||||
private void handleTaskResult(ChangeEncryptionTask.Result result) {
|
||||
setupUiForTaskState(false);
|
||||
|
||||
@Override
|
||||
void onTaskResult(ChangeEncryptionTask.Result result) {
|
||||
switch (result.result) {
|
||||
case SUCCESS:
|
||||
onSuccessfulEncryptionChange(result.encryptionType, result.newEncryptionKey);
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_change_success, Toast.LENGTH_LONG).show();
|
||||
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_change_success, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
break;
|
||||
case BACKUP_FAILURE:
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_backup_failed, Toast.LENGTH_LONG).show();
|
||||
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_backup_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
break;
|
||||
case CHANGE_FAILURE:
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_change_failed, Toast.LENGTH_LONG).show();
|
||||
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_change_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove the task fragment after the task is finished
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SettingsActivity.TaskFragment findTaskFragment() {
|
||||
return (SettingsActivity.TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||
}
|
||||
|
||||
private void startEncryptionChangeTask(EncryptionType newEnc, byte[] newKey) {
|
||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
||||
// Don't start a task if we already have an active task running.
|
||||
if (taskFragment == null || taskFragment.task.isCanceled()) {
|
||||
ChangeEncryptionTask task = new ChangeEncryptionTask(this, encryptionKey, newEnc, newKey);
|
||||
task.setCallback(this::handleTaskResult);
|
||||
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new SettingsActivity.TaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.commit();
|
||||
startBackgroundTask(task);
|
||||
}
|
||||
|
||||
taskFragment.startTask(task);
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBackgroundTask() {
|
||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.task.isCanceled()) {
|
||||
// The task was canceled, so remove the task fragment
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.commit();
|
||||
setupUiForTaskState(false);
|
||||
} else {
|
||||
taskFragment.task.setCallback(this::handleTaskResult);
|
||||
setupUiForTaskState(true);
|
||||
}
|
||||
} else {
|
||||
setupUiForTaskState(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupUiForTaskState(boolean taskRunning) {
|
||||
@Override
|
||||
protected void setupUiForTaskState(boolean taskRunning) {
|
||||
if (taskRunning) {
|
||||
canGoBack = false;
|
||||
|
||||
// TODO: Better in-progress notification
|
||||
inProgress = Toast.makeText(this, R.string.settings_toast_encryption_changing, Toast.LENGTH_LONG);
|
||||
inProgress = Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_changing, BaseTransientBottomBar.LENGTH_INDEFINITE);
|
||||
inProgress.show();
|
||||
|
||||
canGoBack = false;
|
||||
} else {
|
||||
canGoBack = true;
|
||||
|
||||
if (inProgress != null)
|
||||
inProgress.cancel();
|
||||
}
|
||||
}
|
||||
inProgress.dismiss();
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkBackgroundTask();
|
||||
canGoBack = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
||||
|
||||
if (taskFragment != null)
|
||||
taskFragment.task.setCallback(null);
|
||||
}
|
||||
|
||||
private void requestBackupAccess() {
|
||||
|
@ -344,10 +279,10 @@ public class SettingsActivity extends BaseActivity
|
|||
EncryptionType newEncType = EncryptionType.valueOf(newEnc);
|
||||
startEncryptionChangeTask(newEncType, authKey);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_no_key, Toast.LENGTH_LONG).show();
|
||||
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_no_key, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_auth_failed, Toast.LENGTH_LONG).show();
|
||||
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_auth_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||
}
|
||||
} else if (requestCode == Constants.INTENT_SETTINGS_BACKUP_LOCATION && resultCode == RESULT_OK) {
|
||||
Uri treeUri = data.getData();
|
||||
|
@ -573,19 +508,4 @@ public class SettingsActivity extends BaseActivity
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Retained instance fragment to hold a running {@link ChangeEncryptionTask} between configuration changes.*/
|
||||
public static class TaskFragment extends Fragment {
|
||||
ChangeEncryptionTask task;
|
||||
|
||||
public TaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void startTask(@NonNull ChangeEncryptionTask task) {
|
||||
this.task = task;
|
||||
task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import android.content.Intent;
|
|||
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||
|
@ -81,9 +81,9 @@ public class EncryptedBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
|||
task.execute();
|
||||
}
|
||||
|
||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
||||
private void handleTaskResult(BackupTaskResult result) {
|
||||
if (result.success) {
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.fileName);
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.payload);
|
||||
} else {
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import android.content.Intent;
|
|||
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
|
@ -74,9 +74,9 @@ public class PlainTextBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
|||
task.execute();
|
||||
}
|
||||
|
||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
||||
private void handleTaskResult(BackupTaskResult result) {
|
||||
if (result.success) {
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.fileName);
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.payload);
|
||||
} else {
|
||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
|
||||
public class BackupTaskResult {
|
||||
public final boolean success;
|
||||
public final String payload;
|
||||
public final int messageId;
|
||||
|
||||
public boolean isPGP = false;
|
||||
public Intent decryptIntent = null;
|
||||
public Uri uri = null;
|
||||
|
||||
public final ResultType resultType;
|
||||
|
||||
public enum ResultType {
|
||||
NONE, BACKUP, RESTORE
|
||||
}
|
||||
|
||||
public BackupTaskResult(ResultType type, boolean success, String payload, int messageId) {
|
||||
this.resultType = type;
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
public BackupTaskResult(ResultType type, boolean success, String payload, int messageId, boolean isPGP, Intent decryptIntent, Uri uri) {
|
||||
this.resultType = type;
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
this.isPGP = isPGP;
|
||||
this.decryptIntent = decryptIntent;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public static BackupTaskResult success(ResultType type, String payload) {
|
||||
return new BackupTaskResult(type, true, payload, R.string.backup_toast_export_success);
|
||||
}
|
||||
|
||||
public static BackupTaskResult failure(ResultType type, int messageId) {
|
||||
return new BackupTaskResult(type, false, null, messageId);
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ public class EncryptedRestoreTask extends GenericRestoreTask {
|
|||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
protected BackupTaskResult doInBackground() {
|
||||
boolean success = true;
|
||||
String decryptedString = "";
|
||||
|
||||
|
@ -58,9 +58,9 @@ public class EncryptedRestoreTask extends GenericRestoreTask {
|
|||
}
|
||||
|
||||
if (success) {
|
||||
return RestoreTaskResult.success(decryptedString);
|
||||
return BackupTaskResult.success(BackupTaskResult.ResultType.RESTORE, decryptedString);
|
||||
} else {
|
||||
return RestoreTaskResult.failure(R.string.backup_toast_import_decryption_failed);
|
||||
return BackupTaskResult.failure(BackupTaskResult.ResultType.RESTORE, R.string.backup_toast_import_decryption_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ import org.shadowice.flocke.andotp.Utilities.Constants;
|
|||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||
|
||||
public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBackupTask.BackupTaskResult> {
|
||||
public abstract class GenericBackupTask extends UiBasedBackgroundTask<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());
|
||||
super(BackupTaskResult.failure(BackupTaskResult.ResultType.BACKUP, R.string.backup_toast_export_failed));
|
||||
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.settings = new Settings(applicationContext);
|
||||
|
@ -37,7 +37,7 @@ public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBac
|
|||
BackupHelper.BackupFile backupFile = BackupHelper.backupFile(applicationContext, settings.getBackupLocation(), type);
|
||||
|
||||
if (backupFile.file == null)
|
||||
return new BackupTaskResult(false, backupFile.errorMessage, null);
|
||||
return new BackupTaskResult(BackupTaskResult.ResultType.BACKUP,false, null, backupFile.errorMessage);
|
||||
|
||||
uri = backupFile.file.getUri();
|
||||
fileName = backupFile.file.getName();
|
||||
|
@ -48,33 +48,12 @@ public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBac
|
|||
boolean success = doBackup();
|
||||
|
||||
if (success)
|
||||
return BackupTaskResult.success(fileName);
|
||||
return BackupTaskResult.success(BackupTaskResult.ResultType.BACKUP ,fileName);
|
||||
else
|
||||
return BackupTaskResult.failure();
|
||||
return BackupTaskResult.failure(BackupTaskResult.ResultType.BACKUP, R.string.backup_toast_export_failed);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract Constants.BackupType getBackupType();
|
||||
protected abstract boolean doBackup();
|
||||
|
||||
|
||||
public static class BackupTaskResult {
|
||||
public final boolean success;
|
||||
public final int messageId;
|
||||
public final String fileName;
|
||||
|
||||
public BackupTaskResult(boolean success, int messageId, String fileName) {
|
||||
this.success = success;
|
||||
this.messageId = messageId;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public static BackupTaskResult success(String fileName) {
|
||||
return new BackupTaskResult(true, R.string.backup_toast_export_success, fileName);
|
||||
}
|
||||
|
||||
public static BackupTaskResult failure() {
|
||||
return new BackupTaskResult(false, R.string.backup_toast_export_failed, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -10,13 +9,13 @@ import androidx.annotation.Nullable;
|
|||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||
|
||||
public abstract class GenericRestoreTask extends UiBasedBackgroundTask<GenericRestoreTask.RestoreTaskResult> {
|
||||
public abstract class GenericRestoreTask extends UiBasedBackgroundTask<BackupTaskResult> {
|
||||
protected final Context applicationContext;
|
||||
protected final Settings settings;
|
||||
protected Uri uri;
|
||||
|
||||
public GenericRestoreTask(Context context, @Nullable Uri uri) {
|
||||
super(GenericRestoreTask.RestoreTaskResult.failure(R.string.backup_toast_import_failed));
|
||||
super(BackupTaskResult.failure(BackupTaskResult.ResultType.RESTORE, R.string.backup_toast_import_failed));
|
||||
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.settings = new Settings(applicationContext);
|
||||
|
@ -26,38 +25,5 @@ public abstract class GenericRestoreTask extends UiBasedBackgroundTask<GenericRe
|
|||
|
||||
@Override
|
||||
@NonNull
|
||||
protected abstract RestoreTaskResult doInBackground();
|
||||
|
||||
public static class RestoreTaskResult {
|
||||
public final boolean success;
|
||||
public final String payload;
|
||||
public final int messageId;
|
||||
|
||||
public boolean isPGP = false;
|
||||
public Intent decryptIntent = null;
|
||||
public Uri uri = null;
|
||||
|
||||
public RestoreTaskResult(boolean success, String payload, int messageId) {
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
public RestoreTaskResult(boolean success, String payload, int messageId, boolean isPGP, Intent decryptIntent, Uri uri) {
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
this.isPGP = isPGP;
|
||||
this.decryptIntent = decryptIntent;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public static RestoreTaskResult success(String payload) {
|
||||
return new RestoreTaskResult(true, payload, 0);
|
||||
}
|
||||
|
||||
public static RestoreTaskResult failure(int messageId) {
|
||||
return new RestoreTaskResult(false, null, messageId);
|
||||
}
|
||||
}
|
||||
protected abstract BackupTaskResult doInBackground();
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ public class PGPRestoreTask extends GenericRestoreTask {
|
|||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
protected BackupTaskResult doInBackground() {
|
||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||
|
||||
return new RestoreTaskResult(true, data, 0, true, decryptIntent, uri);
|
||||
return new BackupTaskResult(BackupTaskResult.ResultType.RESTORE,true, data, 0, true, decryptIntent, uri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ public class PlainTextRestoreTask extends GenericRestoreTask {
|
|||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
protected BackupTaskResult doInBackground() {
|
||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||
return RestoreTaskResult.success(data);
|
||||
return BackupTaskResult.success(BackupTaskResult.ResultType.RESTORE, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ public abstract class UiBasedBackgroundTask<Result> {
|
|||
private Result awaitedResult;
|
||||
|
||||
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). */
|
||||
public UiBasedBackgroundTask(@NonNull Result failedResult) {
|
||||
|
@ -53,10 +52,7 @@ public abstract class UiBasedBackgroundTask<Result> {
|
|||
}
|
||||
|
||||
private void emitResultOnMainThread(@NonNull UiCallback<Result> callback, @NonNull Result result) {
|
||||
mainThreadHandler.post(() -> {
|
||||
callback.onResult(result);
|
||||
isRunning = false;
|
||||
});
|
||||
mainThreadHandler.post(() -> callback.onResult(result));
|
||||
this.callback = null;
|
||||
this.awaitedResult = null;
|
||||
}
|
||||
|
@ -64,7 +60,6 @@ public abstract class UiBasedBackgroundTask<Result> {
|
|||
/** Executed the task on a background thread. Safe to call from the main thread. */
|
||||
@AnyThread
|
||||
public void execute() {
|
||||
isRunning = true;
|
||||
executor.execute(this::runTask);
|
||||
}
|
||||
|
||||
|
@ -101,15 +96,9 @@ public abstract class UiBasedBackgroundTask<Result> {
|
|||
return isCanceled;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public void cancel() {
|
||||
isCanceled = true;
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -63,8 +63,8 @@ import org.shadowice.flocke.andotp.Database.Entry;
|
|||
import org.shadowice.flocke.andotp.Database.EntryList;
|
||||
import org.shadowice.flocke.andotp.Dialogs.ManualEntryDialog;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
||||
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
|
@ -198,7 +198,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
|||
}
|
||||
}
|
||||
|
||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
||||
private void handleTaskResult(BackupTaskResult result) {
|
||||
if (result.success) {
|
||||
Toast.makeText(context, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
|
@ -270,9 +270,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
|||
|
||||
Constants.CardLayouts layout = settings.getCardLayout();
|
||||
|
||||
if (layout == Constants.CardLayouts.DEFAULT) {
|
||||
cardLayout = R.layout.component_card_default;
|
||||
} else if (layout == Constants.CardLayouts.COMPACT) {
|
||||
if (layout == Constants.CardLayouts.COMPACT) {
|
||||
cardLayout = R.layout.component_card_compact;
|
||||
} else if (layout == Constants.CardLayouts.FULL) {
|
||||
cardLayout = R.layout.component_card_full;
|
||||
|
@ -371,7 +369,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
|||
private void copyHandler(final int position, final String text, final boolean dropToBackground) {
|
||||
Tools.copyToClipboard(context, text);
|
||||
updateLastUsedAndFrequency(position, getRealIndex(position));
|
||||
if(context != null && dropToBackground) {
|
||||
if (dropToBackground) {
|
||||
((MainActivity)context).moveTaskToBack(true);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue