/* Class that handles the Local Storage Options seen in the Options screen
* Allows user to make a local backup to a custom folder
* and restore from a local backup file
* No error checking yet...
*/
package com.databases.example.app;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.design.widget.TextInputEditText;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.databases.example.R;
import com.databases.example.database.DatabaseHelper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import timber.log.Timber;
public class BackupActivity extends AppCompatActivity {
private final static String DEFAULT_BACKUP_DIR = "/WelshFinanceBackUps";
private final static int PICKFILE_RESULT_CODE = 123;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sd);
setTitle(getString(R.string.local_backup));
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}//end onCreate
//For Menu Items
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
break;
}
return super.onOptionsItemSelected(item);
}
public void sdRestore(View v) {
try {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite()) {
Timber.v("SD can write into");
try {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
} catch (ActivityNotFoundException e) {
Timber.e("No program to handle intent? Error e=" + e);
Toast.makeText(this, "Please install a file manager", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Timber.e("Error e = " + e);
}
} else {
Timber.w("Cannot write into SD");
Toast.makeText(this, "No SD Card Found!", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Timber.e("Error restoring. e=" + e);
Toast.makeText(this, "Error restoring \n" + e, Toast.LENGTH_LONG).show();
}
}
public void sdBackup(View v) {
TextInputEditText tvLogStatus = (TextInputEditText) findViewById(R.id.backup_directory);
String customBackupDir = tvLogStatus.getText().toString().trim();
DialogFragment newFragment = BackupDialogFragment.newInstance(customBackupDir);
newFragment.show(getSupportFragmentManager(), "dialogBackup");
}
public static class BackupDialogFragment extends DialogFragment {
public static BackupDialogFragment newInstance(String customBackupDir) {
BackupDialogFragment frag = new BackupDialogFragment();
Bundle args = new Bundle();
frag.setArguments(args);
args.putString("customBackupDir", customBackupDir);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater li = LayoutInflater.from(this.getActivity());
final View categoryAddView = li.inflate(R.layout.sd_backup, null);
final String customBackupDir = getArguments().getString("customBackupDir");
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
//set account_add.xml to AlertDialog builder
alertDialogBuilder.setView(categoryAddView);
//set Title
alertDialogBuilder.setTitle("Creating A Backup");
//set dialog message
alertDialogBuilder
.setCancelable(true)
.setPositiveButton("Backup", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
TextInputEditText backupTextBox = (TextInputEditText) categoryAddView.findViewById(R.id.backup_name);
String backupName = backupTextBox.getText().toString().trim();
/**
* Code derived from StackOverflow
* http://stackoverflow.com/questions/1995320/how-to-backup-database-file-to-sdcard-on-android
**/
try {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite()) {
Timber.v("SD can write into");
File backupDir;
//Handle Custom Directory
if (customBackupDir.matches("")) {
Timber.d("Use default directory");
backupDir = new File(sd.getAbsoluteFile() + DEFAULT_BACKUP_DIR);
backupDir.mkdir();
} else {
Timber.d("Use custom directory");
if (!customBackupDir.startsWith("/")) {
backupDir = new File(sd.getAbsoluteFile() + "/" + customBackupDir);
} else {
backupDir = new File(sd.getAbsoluteFile() + customBackupDir);
}
backupDir.mkdir();
}
DatabaseHelper dh = new DatabaseHelper(getActivity());
String backupDBPath = backupDir.getAbsolutePath() + "/" + backupName;
File currentDB = dh.getDatabase();
File backupDB = new File(backupDBPath);
if (currentDB.exists()) {
Timber.d("currentDB exists");
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Timber.d("Successfully backed up database to " + backupDB.getAbsolutePath());
Toast.makeText(getActivity(), "Your backup\n" + backupDB.getAbsolutePath(), Toast.LENGTH_LONG).show();
}
} else {
Timber.e("Cannot write into SD");
Toast.makeText(getActivity(), "No SD Card Found!", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Timber.e("Error backing up. e=" + e);
Toast.makeText(getActivity(), "Error backing up \n" + e, Toast.LENGTH_LONG).show();
}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
return alertDialogBuilder.create();
}
}
//Method called after picking a file
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PICKFILE_RESULT_CODE:
if (resultCode == RESULT_OK) {
Timber.v("OK. Picked " + getPath(data.getData()));
DatabaseHelper dh = new DatabaseHelper(this);
String restoreDBPath = getPath(data.getData());
File currentDB = dh.getDatabase();
File restoreDB = new File(restoreDBPath);
//write restore file into current database file
try {
FileChannel src = new FileInputStream(restoreDB).getChannel();
FileChannel dst = new FileOutputStream(currentDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Timber.d("Successfully restored database to " + restoreDB.getAbsolutePath());
Toast.makeText(this, "You restored from \n" + restoreDB.getAbsolutePath(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Timber.e("Restore failed \n" + e);
Toast.makeText(this, "Restore failed \n" + e, Toast.LENGTH_LONG).show();
}
}
if (resultCode == RESULT_CANCELED) {
Timber.w("canceled");
}
break;
}
}
//Method finds path name, both from gallery or file manager
private String getPath(Uri uri) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(uri, projection, null, null, null);
String linkFilePath;
if (cursor != null) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
linkFilePath = cursor.getString(column_index);
} else {
linkFilePath = uri.getPath();
}
return linkFilePath;
}
}