org.totschnig.myexpenses.activity.BackupRestoreActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.totschnig.myexpenses.activity.BackupRestoreActivity.java

Source

/*   This file is part of My Expenses.
 *   My Expenses is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   My Expenses is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with My Expenses.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.totschnig.myexpenses.activity;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

import org.totschnig.myexpenses.MyApplication;
import org.totschnig.myexpenses.R;
import org.totschnig.myexpenses.dialog.BackupListDialogFragment;
import org.totschnig.myexpenses.dialog.BackupSourcesDialogFragment;
import org.totschnig.myexpenses.dialog.ConfirmationDialogFragment;
import org.totschnig.myexpenses.dialog.DialogUtils;
import org.totschnig.myexpenses.dialog.ConfirmationDialogFragment.ConfirmationDialogListener;
import org.totschnig.myexpenses.dialog.MessageDialogFragment;
import org.totschnig.myexpenses.dialog.ProgressDialogFragment;

import static org.totschnig.myexpenses.task.RestoreTask.KEY_DIR_NAME_LEGACY;

import org.totschnig.myexpenses.preference.PrefKey;
import org.totschnig.myexpenses.task.TaskExecutionFragment;
import org.totschnig.myexpenses.util.FileUtils;
import org.totschnig.myexpenses.util.Result;
import org.totschnig.myexpenses.util.Utils;

import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.provider.DocumentFile;
import android.widget.Toast;

public class BackupRestoreActivity extends ProtectedFragmentActivity implements ConfirmationDialogListener {
    public static final String KEY_RESTORE_PLAN_STRATEGY = "restorePlanStrategy";
    public static final String FRAGMENT_TAG = "BACKUP_SOURCE";

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTheme(MyApplication.getThemeIdTranslucent());
        if (savedInstanceState != null) {
            return;
        }
        String action = getIntent().getAction();
        if (action != null && action.equals("myexpenses.intent.backup")) {
            Result appDirStatus = Utils.checkAppDir();
            if (!appDirStatus.success) {
                abort(appDirStatus.print(this));
                return;
            }
            MessageDialogFragment.newInstance(R.string.menu_backup,
                    getString(R.string.warning_backup, FileUtils.getPath(this, Utils.getAppDir().getUri())),
                    new MessageDialogFragment.Button(android.R.string.yes, R.id.BACKUP_COMMAND, null), null,
                    MessageDialogFragment.Button.noButton()).show(getSupportFragmentManager(), "BACKUP");
        } else {
            if (getIntent().getBooleanExtra("legacy", false)) {
                Result appDirStatus = Utils.checkAppDir();
                if (appDirStatus.success) {
                    openBrowse();
                } else {
                    abort(appDirStatus.print(this));
                }
            } else {
                BackupSourcesDialogFragment.newInstance().show(getSupportFragmentManager(), FRAGMENT_TAG);
            }
        }
    }

    private void abort(String message) {
        Toast.makeText(getBaseContext(), message, Toast.LENGTH_LONG).show();
        setResult(RESULT_CANCELED);
        finish();
    }

    private void showRestoreDialog(Uri fileUri, int restorePlanStrategie) {
        Bundle b = new Bundle();
        b.putInt(ConfirmationDialogFragment.KEY_TITLE, R.string.pref_restore_title);
        b.putString(ConfirmationDialogFragment.KEY_MESSAGE,
                getString(R.string.warning_restore, DialogUtils.getDisplayName(fileUri)));
        b.putInt(ConfirmationDialogFragment.KEY_COMMAND_POSITIVE, R.id.RESTORE_COMMAND);
        b.putInt(KEY_RESTORE_PLAN_STRATEGY, restorePlanStrategie);
        b.putParcelable(TaskExecutionFragment.KEY_FILE_PATH, fileUri);
        ConfirmationDialogFragment.newInstance(b).show(getSupportFragmentManager(), "RESTORE");
    }

    /**
     * Legacy version for backups stored in application directory
     *
     * @param dir
     */
    private void showRestoreDialog(String dir) {
        Bundle b = new Bundle();
        b.putInt(ConfirmationDialogFragment.KEY_TITLE, R.string.pref_restore_title);
        b.putString(ConfirmationDialogFragment.KEY_MESSAGE, getString(R.string.warning_restore, dir));
        b.putInt(ConfirmationDialogFragment.KEY_COMMAND_POSITIVE, R.id.RESTORE_COMMAND);
        b.putString(KEY_DIR_NAME_LEGACY, dir);
        ConfirmationDialogFragment.newInstance(b).show(getSupportFragmentManager(), "RESTORE");
    }

    @Override
    public boolean dispatchCommand(int command, Object tag) {
        if (super.dispatchCommand(command, tag))
            return true;
        switch (command) {
        case R.id.BACKUP_COMMAND:
            if (Utils.checkAppFolderWarning()) {
                doBackup();
            } else {
                Bundle b = new Bundle();
                b.putInt(ConfirmationDialogFragment.KEY_TITLE, R.string.dialog_title_attention);
                b.putString(ConfirmationDialogFragment.KEY_MESSAGE,
                        getString(R.string.warning_app_folder_will_be_deleted_upon_uninstall));
                b.putInt(ConfirmationDialogFragment.KEY_COMMAND_POSITIVE, R.id.BACKUP_COMMAND_DO);
                b.putString(ConfirmationDialogFragment.KEY_PREFKEY, PrefKey.APP_FOLDER_WARNING_SHOWN.getKey());
                ConfirmationDialogFragment.newInstance(b).show(getSupportFragmentManager(), "APP_FOLDER_WARNING");
            }
            return true;
        }
        return false;
    }

    protected void doBackup() {
        Result appDirStatus = Utils.checkAppDir();//TODO this check leads to strict mode violation, can we get rid of it ?
        if (appDirStatus.success) {
            startTaskExecution(TaskExecutionFragment.TASK_BACKUP, null, null, R.string.menu_backup);
        } else {
            Toast.makeText(getBaseContext(), appDirStatus.print(this), Toast.LENGTH_LONG).show();
            finish();
        }
    }

    @Override
    public void onPostExecute(int taskId, Object result) {
        super.onPostExecute(taskId, result);
        Result r = (Result) result;
        switch (taskId) {
        case TaskExecutionFragment.TASK_RESTORE:
            String msg = r.print(this);
            if (msg != null) {
                Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
            }
            if (r.success) {
                MyApplication.getInstance().getLicenceHandler().invalidate();
                // if the backup is password protected, we want to force the password
                // check
                // is it not enough to set mLastPause to zero, since it would be
                // overwritten by the callings activity onpause
                // hence we need to set isLocked if necessary
                MyApplication.getInstance().resetLastPause();
                MyApplication.getInstance().shouldLock(this);

                setResult(RESULT_FIRST_USER);
            }
            break;
        case TaskExecutionFragment.TASK_BACKUP:
            if (!r.success) {
                Toast.makeText(getBaseContext(), r.print(this), Toast.LENGTH_LONG).show();
            } else {
                Uri backupFileUri = (Uri) r.extra[0];
                Toast.makeText(getBaseContext(), getString(r.getMessage(), FileUtils.getPath(this, backupFileUri)),
                        Toast.LENGTH_LONG).show();
                if (PrefKey.PERFORM_SHARE.getBoolean(false)) {
                    ArrayList<Uri> uris = new ArrayList<>();
                    uris.add(backupFileUri);
                    Utils.share(this, uris, PrefKey.SHARE_TARGET.getString("").trim(), "application/zip");
                }
            }
        }
        finish();
    }

    @Override
    public void onProgressUpdate(Object progress) {
        Toast.makeText(getBaseContext(), ((Result) progress).print(this), Toast.LENGTH_LONG).show();
    }

    public void onSourceSelected(Uri mUri, int restorePlanStrategie) {
        showRestoreDialog(mUri, restorePlanStrategie);
    }

    /**
     * Legacy callback from BackupListDialogFragment for backups stored in
     * application directory
     *
     * @param dirOrFile
     */
    public void onSourceSelected(String dirOrFile, int restorePlanStrategie) {
        if (dirOrFile.endsWith(".zip")) {
            showRestoreDialog(Uri.fromFile(new File(Utils.getAppDir().getUri().getPath(), dirOrFile)),
                    restorePlanStrategie);
        } else {
            showRestoreDialog(dirOrFile);
        }
    }

    @Override
    public void onPositive(Bundle args) {
        switch (args.getInt(ConfirmationDialogFragment.KEY_COMMAND_POSITIVE)) {
        case R.id.BACKUP_COMMAND_DO:
            doBackup();
            break;
        case R.id.RESTORE_COMMAND:
            getSupportFragmentManager().beginTransaction()
                    .add(TaskExecutionFragment.newInstanceRestore(args), ProtectionDelegate.ASYNC_TAG)
                    .add(ProgressDialogFragment.newInstance(R.string.pref_restore_title),
                            ProtectionDelegate.PROGRESS_TAG)
                    .commit();
            break;
        }
    }

    public void openBrowse() {
        String[] backups = listBackups();
        if (backups.length == 0) {
            Toast.makeText(getBaseContext(), getString(R.string.restore_no_backup_found), Toast.LENGTH_LONG).show();
            finish();
        } else {
            BackupListDialogFragment.newInstance(backups).show(getSupportFragmentManager(), FRAGMENT_TAG);
        }
    }

    // inspired by Financisto
    public static String[] listBackups() {
        DocumentFile appDir = Utils.getAppDir();
        if (appDir.getUri().getScheme().equals("file")) {
            String[] files = new File(appDir.getUri().getPath()).list(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String filename) {
                    // backup-yyyMMdd-HHmmss
                    return filename.matches("backup-\\d\\d\\d\\d\\d\\d\\d\\d-\\d\\d\\d\\d\\d\\d")
                            || filename.endsWith(".zip");
                }
            });
            if (files != null) {
                Arrays.sort(files, new Comparator<String>() {
                    @Override
                    public int compare(String s1, String s2) {
                        return s2.compareTo(s1);
                    }
                });
                return files;
            }
        }
        return new String[0];
    }

    @Override
    public void onNegative(Bundle args) {
        setResult(RESULT_CANCELED);
        finish();
    }

    @Override
    public void onDismissOrCancel(Bundle args) {
        setResult(RESULT_CANCELED);
        finish();
    }

    @Override
    public void onMessageDialogDismissOrCancel() {
        setResult(RESULT_CANCELED);
        finish();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
        case ProtectionDelegate.PERMISSIONS_REQUEST_WRITE_CALENDAR:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
                Toast.makeText(this, getString(R.string.calendar_permission_required), Toast.LENGTH_LONG).show();
                ((DialogUtils.CalendarRestoreStrategyChangedListener) getSupportFragmentManager()
                        .findFragmentByTag(FRAGMENT_TAG)).onCalendarPermissionDenied();
            }
            break;
        }
    }
}