package com.u17od.upm;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.exception.DropboxUnlinkedException;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;
public class SyncDatabaseViaDropboxActivity extends SyncDatabaseActivity {
private static final String RETURNING_FROM_DB_AUTH = "retDBAuth";
private DropboxAPI<AndroidAuthSession> mDBApi;
private boolean returningFromDropboxAuthentication;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null){
returningFromDropboxAuthentication =
savedInstanceState.getBoolean(
RETURNING_FROM_DB_AUTH, false);
}
prepareDropboxAPI();
}
@Override
protected void onResume() {
super.onResume();
if (returningFromDropboxAuthentication) {
// We'll reach here if we're returning from the Dropbox
// authentication activity. If auth was successful then download
// the database file. Otherwise leave the activity and abort the
// sync.
if (mDBApi.getSession().authenticationSuccessful()) {
// MANDATORY call to complete auth.
// Sets the access token on the session
mDBApi.getSession().finishAuthentication();
// store the tokens so we don't need to authenticate again
// during this session
AccessTokenPair tokens = mDBApi.getSession().getAccessTokenPair();
Utilities.setDropboxAccessTokenPair(this, tokens);
downloadDatabase();
} else {
finish();
}
} else {
// We'll reach here if we're entering the activity after selecting
// the "Sync" menu option.
downloadDatabase();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(RETURNING_FROM_DB_AUTH,
returningFromDropboxAuthentication);
}
private void prepareDropboxAPI() {
// Prepare Dropbox Session objects
AppKeyPair appKeys = new AppKeyPair(DropboxConstants.APP_KEY, DropboxConstants.APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeys, DropboxConstants.ACCESS_TYPE);
mDBApi = new DropboxAPI<AndroidAuthSession>(session);
AccessTokenPair accessTokenPair = Utilities.getDropboxAccessTokenPair(this);
if (accessTokenPair != null) {
mDBApi.getSession().setAccessTokenPair(accessTokenPair);
}
}
@Override
protected void uploadDatabase() {
new UploadDatabaseTask().execute();
}
@Override
protected void downloadDatabase() {
new DownloadDatabaseTask().execute();
}
private class DownloadDatabaseTask extends AsyncTask<Void, Void, Integer> {
private static final int ERROR_IO_ERROR = 1;
private static final int ERROR_DROPBOX_UNLINKED = 2;
private static final int ERROR_DROPBOX_ERROR = 3;
private ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(SyncDatabaseViaDropboxActivity.this,
"", getString(R.string.downloading_db));
if (mDBApi == null) {
prepareDropboxAPI();
}
}
@Override
protected Integer doInBackground(Void... params) {
FileOutputStream outputStream = null;
try {
// Download the file and save it to a temp file
String remoteFileName = Utilities.getDatabaseFileName(SyncDatabaseViaDropboxActivity.this);
downloadedDatabaseFile = new File(getCacheDir(), remoteFileName);
outputStream = new FileOutputStream(downloadedDatabaseFile);
DropboxAPI.DropboxFileInfo downloadedFileInfo =
mDBApi.getFile(remoteFileName, null, outputStream, null);
// Store the db file rev for use in the UploadDatabaseTask
// Prefs is used instead of the activity instance because the
// activity could be recreate between now and then meaning the
// instance variables are reset.
Utilities.setConfig(SyncDatabaseViaDropboxActivity.this,
Utilities.DROPBOX_PREFS, Utilities.DROPBOX_DB_REV,
downloadedFileInfo.getMetadata().rev);
return 0;
} catch (IOException e) {
Log.e("DownloadDropboxFileActivity.DownloadFileTask",
"IOException", e);
return ERROR_IO_ERROR;
} catch (DropboxUnlinkedException e) {
Log.e("DownloadDropboxFileActivity.DownloadFileTask",
"Dropbox unlinked exception", e);
return ERROR_DROPBOX_UNLINKED;
} catch (DropboxServerException e) {
// 404 is a valid response. Just means we haven't uploaded yet
if (e.error != DropboxServerException._404_NOT_FOUND){
Log.e("DownloadDropboxFileActivity.DownloadFileTask",
"Dropbox server exception", e);
return ERROR_DROPBOX_ERROR;
} else {
downloadedDatabaseFile = null;
return 0;
}
} catch (DropboxException e) {
Log.e("DownloadDropboxFileActivity.DownloadFileTask",
"Dropbox exception", e);
return ERROR_DROPBOX_ERROR;
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
Log.e("DownloadDropboxFileActivity.DownloadFileTask",
"IOException", e);
return ERROR_IO_ERROR;
}
}
}
}
@Override
protected void onPostExecute(Integer result) {
progressDialog.dismiss();
switch (result) {
case 0:
decryptDatabase();
break;
case ERROR_IO_ERROR:
UIUtilities.showToast(SyncDatabaseViaDropboxActivity.this,
R.string.problem_saving_db, true);
finish();
break;
case ERROR_DROPBOX_UNLINKED:
returningFromDropboxAuthentication = true;
mDBApi.getSession().startAuthentication(SyncDatabaseViaDropboxActivity.this);
break;
case ERROR_DROPBOX_ERROR:
UIUtilities.showToast(SyncDatabaseViaDropboxActivity.this,
R.string.dropbox_problem, true);
finish();
break;
}
}
}
private class UploadDatabaseTask extends AsyncTask<Void, Void, Integer> {
private static final int UPLOAD_OK = 0;
private static final int ERROR_READING = 1;
private static final int ERROR_DROPBOX = 2;
private ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(
SyncDatabaseViaDropboxActivity.this, "",
getString(R.string.uploading_database));
if (mDBApi == null) {
prepareDropboxAPI();
}
}
@Override
protected Integer doInBackground(Void... params) {
int result = UPLOAD_OK;
FileInputStream inputStream = null;
try {
File databaseFile = getPasswordDatabase().getDatabaseFile();
inputStream = new FileInputStream(databaseFile);
String currentRev = Utilities.getConfig(
SyncDatabaseViaDropboxActivity.this,
Utilities.DROPBOX_PREFS, Utilities.DROPBOX_DB_REV);
mDBApi.putFile(databaseFile.getName(), inputStream,
databaseFile.length(), currentRev, null);
} catch (FileNotFoundException e) {
Log.e("SyncDatabaseViaDropboxActivity",
"Problem reading database file", e);
result = ERROR_READING;
} catch (DropboxException e) {
Log.e("SyncDatabaseViaDropboxActivity",
"Dropbox error", e);
result = ERROR_DROPBOX;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}
return result;
}
@Override
protected void onPostExecute(Integer result) {
progressDialog.dismiss();
switch (result) {
case ERROR_READING:
UIUtilities.showToast(SyncDatabaseViaDropboxActivity.this, R.string.problem_reading_upm_db);
break;
case ERROR_DROPBOX:
UIUtilities.showToast(SyncDatabaseViaDropboxActivity.this, R.string.dropbox_problem);
break;
default:
UIUtilities.showToast(SyncDatabaseViaDropboxActivity.this, R.string.db_sync_complete);
break;
}
finish();
}
}
}