Started implementing GDriveFileStorage

removed unnecessary check for RequiresSetup in PasswordActivity
This commit is contained in:
Philipp Crocoll 2013-10-08 17:01:47 +02:00
parent 4da67d42c0
commit 8c69a0b5bd
2 changed files with 205 additions and 115 deletions

View File

@ -1,7 +1,8 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -11,21 +12,19 @@ import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccoun
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive; import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Children;
import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.ChildList; import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.model.ChildReference;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log;
/*public class GoogleDriveFileStorage
{};*/
public class GoogleDriveFileStorage
{};
/*/
public class GoogleDriveFileStorage implements JavaFileStorage { public class GoogleDriveFileStorage implements JavaFileStorage {
private static Drive service; private static Drive service;
@ -35,35 +34,9 @@ public class GoogleDriveFileStorage implements JavaFileStorage {
static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1; static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1;
static final int REQUEST_AUTHORIZATION = MAGIC_GDRIVE+2; static final int REQUEST_AUTHORIZATION = MAGIC_GDRIVE+2;
class TestConnectionTask extends AsyncTask<Object, Void, Void> final static private String TAG = "KP2AJ";
{
@Override
protected Void doInBackground(Object... params) {
Activity activity = (Activity) params[0];
//try to list files:
//todo: is there a simpler way to test if the user is authorized?
try
{
return true;
}
catch (UserRecoverableAuthIOException e) {
activity.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
catch (Throwable t)
{
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
activity.setResult(Activity.RESULT_CANCELED, data);
activity.finish();
}
}
}
/*
private static void printFilesInFolder(Drive service, String folderId) private static void printFilesInFolder(Drive service, String folderId)
throws IOException { throws IOException {
Children.List request = service.files().list(); Children.List request = service.files().list();
@ -84,44 +57,10 @@ public class GoogleDriveFileStorage implements JavaFileStorage {
request.getPageToken().length() > 0); request.getPageToken().length() > 0);
} }
public boolean tryConnect(Activity activity) {
List<String> scopes = new ArrayList<String>();
scopes.add(DriveScopes.DRIVE);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(activity, scopes);
String storedAccountName = PreferenceManager.getDefaultSharedPreferences(activity).getString("GDRIVE_ACCOUNT_NAME", null);
if (storedAccountName != null)
{
credential.setSelectedAccountName(storedAccountName);
//try to list files:
//todo: is there a simpler way to test if the user is authorized?
try
{
return true;
}
catch (UserRecoverableAuthIOException e) {
activity.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
catch (Throwable t)
{
return false;
}
}
else
{
activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
return false;
}
} }
*/
@Override @Override
public boolean checkForFileChangeFast(String path, public boolean checkForFileChangeFast(String path,
@ -133,7 +72,7 @@ public class GoogleDriveFileStorage implements JavaFileStorage {
@Override @Override
public String getCurrentFileVersionFast(String path) { public String getCurrentFileVersionFast(String path) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return "";
} }
@Override @Override
@ -176,44 +115,149 @@ public class GoogleDriveFileStorage implements JavaFileStorage {
private Drive getDriveService(GoogleAccountCredential credential) { private Drive getDriveService(GoogleAccountCredential credential) {
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential) return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
.setApplicationName("JFSTest")
.build(); .build();
} }
@Override @Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { public void onActivityResult(final JavaFileStorage.FileStorageSetupActivity setupAct, int requestCode, int resultCode, Intent data) {
Log.d(TAG, "ActivityResult: "+requestCode+"/"+resultCode);
switch (requestCode) { switch (requestCode) {
case REQUEST_ACCOUNT_PICKER: case REQUEST_ACCOUNT_PICKER:
Log.d(TAG, "ActivityResult: REQUEST_ACCOUNT_PICKER");
if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) { if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) { if (accountName != null) {
//credential.setSelectedAccountName(accountName); final Activity activity = (Activity)setupAct;
todo final boolean[] result = { false };
Log.d(TAG, "Account name="+accountName);
try {
testAuthAndReturn(setupAct, accountName, activity, result);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "UnsupportedEncodingException: "+e.toString());
Intent retData = new Intent();
retData.putExtra(EXTRA_ERROR_MESSAGE, e.getMessage());
((Activity)activity).setResult(Activity.RESULT_CANCELED, retData);
((Activity)activity).finish();
}
return; return;
} }
} }
todo Log.i(TAG, "Error selecting account");
//Intent retData = new Intent();
//retData.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
((Activity)setupAct).setResult(Activity.RESULT_CANCELED, data);
((Activity)setupAct).finish();
case REQUEST_AUTHORIZATION: case REQUEST_AUTHORIZATION:
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
// App is authorized finishActivityWithSuccess(setupAct);
todo
} else { } else {
// User denied access, show him the account chooser again Log.i(TAG, "Error authenticating");
activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); //Intent retData = new Intent();
//retData.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
((Activity)setupAct).setResult(Activity.RESULT_CANCELED, data);
((Activity)setupAct).finish();
} }
} }
} }
private void testAuthAndReturn(
final JavaFileStorage.FileStorageSetupActivity setupAct,
String accountName, final Activity activity, final boolean[] result)
throws UnsupportedEncodingException {
setupAct.getState().putString(EXTRA_PATH, getProtocolId()+"://"+URLEncoder.encode(accountName, "ISO-8859-1")+"/");
Thread thread = new Thread() {
@Override
public void run() {
//try to list files:
//todo: is there a simpler way to test if the user is authorized?
try
{
Log.d(TAG,"createCred");
GoogleAccountCredential credential = createCredential(activity);
Log.d(TAG,"get files");
Files.List request = getDriveService(credential).files().list();
Log.d(TAG,"get files exec");
request.execute();
Log.d(TAG,"ok!");
result[0] = true;
}
catch (UserRecoverableAuthIOException e) {
Log.d(TAG,"UserRecoverableAuthIOException ");
activity.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
catch (Throwable t)
{
Log.d(TAG, "Exception: " +t.getMessage());
t.printStackTrace();
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
activity.setResult(Activity.RESULT_CANCELED, data);
activity.finish();
}
}// run()
};
thread.start();
try {
thread.join();
if (result[0])
{
finishActivityWithSuccess(setupAct);
}
} catch (InterruptedException e) {
Intent retData = new Intent();
retData.putExtra(EXTRA_ERROR_MESSAGE, e.getMessage());
activity.setResult(Activity.RESULT_CANCELED, retData);
activity.finish();
}
}
private void finishActivityWithSuccess(FileStorageSetupActivity setupActivity) {
Log.d("KP2AJ", "Success with authentcating!");
Activity activity = (Activity)setupActivity;
if (setupActivity.getProcessName().equals(PROCESS_NAME_FILE_USAGE_SETUP))
{
Intent data = new Intent();
data.putExtra(EXTRA_IS_FOR_SAVE, setupActivity.isForSave());
data.putExtra(EXTRA_PATH, setupActivity.getPath());
activity.setResult(RESULT_FILEUSAGE_PREPARED, data);
activity.finish();
return;
}
if (setupActivity.getProcessName().equals(PROCESS_NAME_SELECTFILE))
{
Intent data = new Intent();
data.putExtra(EXTRA_PATH, setupActivity.getState().getString(EXTRA_PATH));
activity.setResult(RESULT_FILECHOOSER_PREPARED, data);
activity.finish();
return;
}
Log.w("KP2AJ", "Unknown process: " + setupActivity.getProcessName());
}
@Override @Override
public void startSelectFile(Activity activity, boolean isForSave, public void startSelectFile(JavaFileStorage.FileStorageSetupInitiatorActivity activity, boolean isForSave,
int requestCode) { int requestCode) {
((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startSelectFileProcess(getProtocolId()+"://", isForSave, requestCode); ((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startSelectFileProcess(getProtocolId()+"://", isForSave, requestCode);
} }
@Override @Override
public void prepareFileUsage(Activity activity, String path, int requestCode) { public void prepareFileUsage(JavaFileStorage.FileStorageSetupInitiatorActivity activity, String path, int requestCode) {
((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startFileUsageProcess(path, requestCode); ((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startFileUsageProcess(path, requestCode);
} }
@ -227,36 +271,89 @@ public class GoogleDriveFileStorage implements JavaFileStorage {
@Override @Override
public void onResume(Activity activity) { public void onResume(JavaFileStorage.FileStorageSetupActivity setupAct) {
JavaFileStorage.FileStorageSetupActivity setupAct = (FileStorageSetupActivity) activity;
if (activity.isFinishing())
return;
if (!hasAccount(setupAct))
{
List<String> scopes = new ArrayList<String>();
scopes.add(DriveScopes.DRIVE);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(activity, scopes);
activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
else
{
}
} }
@Override @Override
public void onStart(Activity activity) { public void onStart(final JavaFileStorage.FileStorageSetupActivity setupAct) {
Activity activity = (Activity)setupAct;
if (PROCESS_NAME_SELECTFILE.equals(setupAct.getProcessName()))
{
GoogleAccountCredential credential = createCredential(activity);
Log.d(TAG, "starting REQUEST_ACCOUNT_PICKER");
activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
if (PROCESS_NAME_FILE_USAGE_SETUP.equals(setupAct.getProcessName()))
{
GoogleAccountCredential credential = createCredential(activity);
String storedAccountName = PreferenceManager.getDefaultSharedPreferences(activity).getString("GDRIVE_ACCOUNT_NAME", null);
if (storedAccountName != null)
{
credential.setSelectedAccountName(storedAccountName);
Thread thread = new Thread() {
@Override
public void run() {
Activity activity = (Activity)setupAct;
//try to list files:
//todo: is there a simpler way to test if the user is authorized?
try
{
service.files().list().execute();
}
catch (UserRecoverableAuthIOException e) {
activity.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
catch (Throwable t)
{
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
activity.setResult(Activity.RESULT_CANCELED, data);
activity.finish();
}
}// run()
};
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, e.getMessage());
activity.setResult(Activity.RESULT_CANCELED, data);
activity.finish();
}
}
}
}
private GoogleAccountCredential createCredential(Activity activity) {
List<String> scopes = new ArrayList<String>();
scopes.add(DriveScopes.DRIVE);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(activity, scopes);
return credential;
}
@Override
public boolean requiresSetup(String path) {
//always send the user through the prepare file usage workflow if he needs to authorize
return true;
}
@Override
public void onCreate(FileStorageSetupActivity activity,
Bundle savedInstanceState) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }
*/

View File

@ -481,15 +481,8 @@ namespace keepass2android
{ {
//database not yet loaded. //database not yet loaded.
//check if FileStorage setup is all done. Usually this should not occur here because the setup is
//performed in FileSelectActivity, but e.g. if the user unlinks from Dropbox saving might fail and
//the user is returned here.
if (App.Kp2a.GetFileStorage(_ioConnection).RequiresSetup(_ioConnection))
{
GoToFileSelectActivity();
}
//check if pre-loading is enabled but wasn't started yet: //check if pre-loading is enabled but wasn't started yet:
else if (_loadDbTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true)) if (_loadDbTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
{ {
// Create task to kick off file loading while the user enters the password // Create task to kick off file loading while the user enters the password
_loadDbTask = Task.Factory.StartNew<MemoryStream>(LoadDbFile); _loadDbTask = Task.Factory.StartNew<MemoryStream>(LoadDbFile);