Java tutorial
/* 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; } } }