2017-09-20 22:42:15 -04:00
|
|
|
package com.stevesoltys.backup.activity;
|
|
|
|
|
|
|
|
import android.app.Activity;
|
2019-06-07 16:41:48 -03:00
|
|
|
import android.app.job.JobInfo;
|
|
|
|
import android.app.job.JobScheduler;
|
2017-09-20 22:42:15 -04:00
|
|
|
import android.content.ActivityNotFoundException;
|
2019-06-07 16:41:48 -03:00
|
|
|
import android.content.ComponentName;
|
2019-06-04 13:27:07 -03:00
|
|
|
import android.content.ContentResolver;
|
2017-09-20 22:42:15 -04:00
|
|
|
import android.content.Intent;
|
2019-06-04 13:27:07 -03:00
|
|
|
import android.net.Uri;
|
2019-06-04 17:45:21 -03:00
|
|
|
import android.util.Log;
|
2017-09-20 22:42:15 -04:00
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import com.stevesoltys.backup.activity.backup.CreateBackupActivity;
|
|
|
|
import com.stevesoltys.backup.activity.restore.RestoreBackupActivity;
|
2019-06-07 16:41:48 -03:00
|
|
|
import com.stevesoltys.backup.service.backup.BackupJobService;
|
2017-09-20 22:42:15 -04:00
|
|
|
|
2019-06-04 13:27:07 -03:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.Date;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
2019-06-07 16:41:48 -03:00
|
|
|
import static android.app.job.JobInfo.NETWORK_TYPE_UNMETERED;
|
2017-09-20 22:42:15 -04:00
|
|
|
import static android.content.Intent.ACTION_OPEN_DOCUMENT;
|
2019-06-04 13:27:07 -03:00
|
|
|
import static android.content.Intent.ACTION_OPEN_DOCUMENT_TREE;
|
2017-09-20 22:42:15 -04:00
|
|
|
import static android.content.Intent.CATEGORY_OPENABLE;
|
2019-06-04 13:27:07 -03:00
|
|
|
import static android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
|
|
|
|
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
|
|
|
import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
|
|
|
import static android.provider.DocumentsContract.buildDocumentUriUsingTree;
|
|
|
|
import static android.provider.DocumentsContract.createDocument;
|
|
|
|
import static android.provider.DocumentsContract.getTreeDocumentId;
|
2019-06-07 16:41:48 -03:00
|
|
|
import static com.stevesoltys.backup.Backup.JOB_ID_BACKGROUND_BACKUP;
|
2019-06-04 16:00:30 -03:00
|
|
|
import static com.stevesoltys.backup.activity.MainActivity.OPEN_DOCUMENT_TREE_BACKUP_REQUEST_CODE;
|
2019-06-04 13:27:07 -03:00
|
|
|
import static com.stevesoltys.backup.activity.MainActivity.OPEN_DOCUMENT_TREE_REQUEST_CODE;
|
2019-06-04 15:19:19 -03:00
|
|
|
import static com.stevesoltys.backup.settings.SettingsManager.getBackupFolderUri;
|
2019-06-07 16:41:48 -03:00
|
|
|
import static com.stevesoltys.backup.settings.SettingsManager.getBackupPassword;
|
2019-06-04 15:19:19 -03:00
|
|
|
import static com.stevesoltys.backup.settings.SettingsManager.setBackupFolderUri;
|
2019-06-07 16:41:48 -03:00
|
|
|
import static com.stevesoltys.backup.settings.SettingsManager.setBackupsScheduled;
|
|
|
|
import static java.util.Objects.requireNonNull;
|
|
|
|
import static java.util.concurrent.TimeUnit.DAYS;
|
2017-09-20 22:42:15 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Steve Soltys
|
2019-06-04 13:27:07 -03:00
|
|
|
* @author Torsten Grote
|
2017-09-20 22:42:15 -04:00
|
|
|
*/
|
2019-06-07 16:41:48 -03:00
|
|
|
public class MainActivityController {
|
2017-09-20 22:42:15 -04:00
|
|
|
|
2019-06-04 17:45:21 -03:00
|
|
|
private static final String TAG = MainActivityController.class.getName();
|
|
|
|
|
2017-09-20 22:42:15 -04:00
|
|
|
private static final String DOCUMENT_MIME_TYPE = "application/octet-stream";
|
2019-06-04 13:27:07 -03:00
|
|
|
private static final String DOCUMENT_SUFFIX = "yyyy-MM-dd_HH_mm_ss";
|
2017-09-20 22:42:15 -04:00
|
|
|
|
2019-06-04 15:19:19 -03:00
|
|
|
void onBackupButtonClicked(Activity parent) {
|
|
|
|
Uri folderUri = getBackupFolderUri(parent);
|
|
|
|
if (folderUri == null) {
|
2019-06-04 16:00:30 -03:00
|
|
|
showChooseFolderActivity(parent, true);
|
2019-06-04 15:19:19 -03:00
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
Uri fileUri = createBackupFile(parent.getContentResolver(), folderUri);
|
|
|
|
showCreateBackupActivity(parent, fileUri);
|
2019-06-04 16:00:30 -03:00
|
|
|
|
2019-06-04 15:19:19 -03:00
|
|
|
} catch (IOException e) {
|
2019-06-04 17:45:21 -03:00
|
|
|
Log.w(TAG, "Error creating backup file: ", e);
|
2019-06-04 16:00:30 -03:00
|
|
|
showChooseFolderActivity(parent, true);
|
2019-06-04 15:19:19 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-04 16:00:30 -03:00
|
|
|
boolean isChangeBackupLocationButtonVisible(Activity parent) {
|
|
|
|
return getBackupFolderUri(parent) != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void showChooseFolderActivity(Activity parent, boolean continueToBackup) {
|
|
|
|
Intent openTreeIntent = new Intent(ACTION_OPEN_DOCUMENT_TREE);
|
|
|
|
openTreeIntent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION |
|
2019-06-04 13:27:07 -03:00
|
|
|
FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
|
2017-09-20 22:42:15 -04:00
|
|
|
|
|
|
|
try {
|
2019-06-04 16:00:30 -03:00
|
|
|
Intent documentChooser = Intent.createChooser(openTreeIntent, "Select the backup location");
|
|
|
|
int requestCode = continueToBackup ? OPEN_DOCUMENT_TREE_BACKUP_REQUEST_CODE : OPEN_DOCUMENT_TREE_REQUEST_CODE;
|
|
|
|
parent.startActivityForResult(documentChooser, requestCode);
|
2017-09-20 22:42:15 -04:00
|
|
|
|
|
|
|
} catch (ActivityNotFoundException ex) {
|
|
|
|
Toast.makeText(parent, "Please install a file manager.", Toast.LENGTH_SHORT).show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void showLoadDocumentActivity(Activity parent) {
|
|
|
|
Intent loadDocumentIntent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
|
|
loadDocumentIntent.addCategory(CATEGORY_OPENABLE);
|
|
|
|
loadDocumentIntent.setType(DOCUMENT_MIME_TYPE);
|
|
|
|
|
|
|
|
try {
|
|
|
|
Intent documentChooser = Intent.createChooser(loadDocumentIntent, "Select the backup location");
|
|
|
|
parent.startActivityForResult(documentChooser, MainActivity.LOAD_DOCUMENT_REQUEST_CODE);
|
|
|
|
|
|
|
|
} catch (ActivityNotFoundException ex) {
|
|
|
|
Toast.makeText(parent, "Please install a file manager.", Toast.LENGTH_SHORT).show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 16:41:48 -03:00
|
|
|
boolean onAutomaticBackupsButtonClicked(Activity parent) {
|
|
|
|
if (getBackupFolderUri(parent) == null || getBackupPassword(parent) == null) {
|
|
|
|
Toast.makeText(parent, "Please make at least one manual backup first.", Toast.LENGTH_SHORT).show();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final ComponentName serviceName = new ComponentName(parent, BackupJobService.class);
|
|
|
|
JobInfo job = new JobInfo.Builder(JOB_ID_BACKGROUND_BACKUP, serviceName)
|
|
|
|
.setRequiredNetworkType(NETWORK_TYPE_UNMETERED)
|
|
|
|
.setRequiresBatteryNotLow(true)
|
|
|
|
.setRequiresStorageNotLow(true) // TODO warn the user instead
|
|
|
|
.setPeriodic(DAYS.toMillis(1))
|
|
|
|
.setRequiresCharging(true)
|
|
|
|
.setPersisted(true)
|
|
|
|
.build();
|
|
|
|
JobScheduler scheduler = requireNonNull(parent.getSystemService(JobScheduler.class));
|
|
|
|
scheduler.schedule(job);
|
|
|
|
setBackupsScheduled(parent);
|
|
|
|
Toast.makeText(parent, "Backups will run automatically now", Toast.LENGTH_SHORT).show();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-06-04 16:00:30 -03:00
|
|
|
void onChangeBackupLocationButtonClicked(Activity parent) {
|
|
|
|
showChooseFolderActivity(parent, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleChooseFolderResult(Intent result, Activity parent, boolean continueToBackup) {
|
2017-09-20 22:42:15 -04:00
|
|
|
|
2019-06-04 13:27:07 -03:00
|
|
|
if (result == null || result.getData() == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Uri folderUri = result.getData();
|
|
|
|
ContentResolver contentResolver = parent.getContentResolver();
|
|
|
|
|
|
|
|
// persist permission to access backup folder across reboots
|
|
|
|
int takeFlags = result.getFlags() &
|
|
|
|
(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
|
|
contentResolver.takePersistableUriPermission(folderUri, takeFlags);
|
|
|
|
|
2019-06-04 15:19:19 -03:00
|
|
|
// store backup folder location in settings
|
|
|
|
setBackupFolderUri(parent, folderUri);
|
|
|
|
|
2019-06-04 16:00:30 -03:00
|
|
|
if (!continueToBackup) return;
|
|
|
|
|
2019-06-04 13:27:07 -03:00
|
|
|
try {
|
2019-06-04 16:00:30 -03:00
|
|
|
// create a new backup file in folder
|
|
|
|
Uri fileUri = createBackupFile(contentResolver, folderUri);
|
|
|
|
|
|
|
|
showCreateBackupActivity(parent, fileUri);
|
|
|
|
|
2019-06-04 13:27:07 -03:00
|
|
|
} catch (IOException e) {
|
2019-06-04 17:45:21 -03:00
|
|
|
Log.e(TAG, "Error creating backup file: ", e);
|
2019-06-04 13:27:07 -03:00
|
|
|
// TODO show better error message once more infrastructure is in place
|
|
|
|
Toast.makeText(parent, "Error creating backup file", Toast.LENGTH_SHORT).show();
|
2017-09-20 22:42:15 -04:00
|
|
|
}
|
2019-06-04 15:19:19 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
private void showCreateBackupActivity(Activity parent, Uri fileUri) {
|
2017-09-20 22:42:15 -04:00
|
|
|
Intent intent = new Intent(parent, CreateBackupActivity.class);
|
2019-06-04 13:27:07 -03:00
|
|
|
intent.setData(fileUri);
|
2017-09-20 22:42:15 -04:00
|
|
|
parent.startActivity(intent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleLoadDocumentResult(Intent result, Activity parent) {
|
|
|
|
|
|
|
|
if (result == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Intent intent = new Intent(parent, RestoreBackupActivity.class);
|
|
|
|
intent.setData(result.getData());
|
|
|
|
parent.startActivity(intent);
|
|
|
|
}
|
2019-06-04 13:27:07 -03:00
|
|
|
|
2019-06-07 16:41:48 -03:00
|
|
|
public static Uri createBackupFile(ContentResolver contentResolver, Uri folderUri) throws IOException {
|
2019-06-04 13:27:07 -03:00
|
|
|
Uri documentUri = buildDocumentUriUsingTree(folderUri, getTreeDocumentId(folderUri));
|
2019-06-04 15:19:19 -03:00
|
|
|
try {
|
|
|
|
Uri fileUri = createDocument(contentResolver, documentUri, DOCUMENT_MIME_TYPE, getBackupFileName());
|
|
|
|
if (fileUri == null) throw new IOException();
|
|
|
|
return fileUri;
|
2019-06-04 16:00:30 -03:00
|
|
|
|
2019-06-04 15:19:19 -03:00
|
|
|
} catch (SecurityException e) {
|
|
|
|
// happens when folder was deleted and thus Uri permission don't exist anymore
|
|
|
|
throw new IOException(e);
|
|
|
|
}
|
2019-06-04 13:27:07 -03:00
|
|
|
}
|
|
|
|
|
2019-06-07 16:41:48 -03:00
|
|
|
private static String getBackupFileName() {
|
2019-06-04 13:27:07 -03:00
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat(DOCUMENT_SUFFIX, Locale.US);
|
|
|
|
String date = dateFormat.format(new Date());
|
|
|
|
return "backup-" + date;
|
|
|
|
}
|
|
|
|
|
2017-09-20 22:42:15 -04:00
|
|
|
}
|