Use asynctask to check for permission

This commit is contained in:
Jimmy Shih
2013-12-09 14:22:17 -08:00
parent caa1680dc6
commit a28c39bea9
3 changed files with 163 additions and 154 deletions
@@ -16,8 +16,6 @@
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment.CheckPermissionCaller;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller;
import com.google.android.apps.mytracks.fragments.ConfirmDeleteDialogFragment;
@@ -40,6 +38,7 @@ import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
import com.google.android.apps.mytracks.io.sync.SyncUtils;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.services.tasks.CheckPermissionAsyncTask;
import com.google.android.apps.mytracks.util.AnalyticsUtils;
import com.google.android.apps.mytracks.util.GoogleEarthUtils;
import com.google.android.apps.mytracks.util.IntentUtils;
@@ -58,7 +57,6 @@ import android.content.ContentResolver;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.widget.Toast;
@@ -70,8 +68,8 @@ import java.io.IOException;
* @author Jimmy Shih
*/
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity implements
ChooseAccountCaller, ConfirmSyncCaller, CheckPermissionCaller, ShareTrackCaller,
ConfirmDeleteCaller, PlayMultipleCaller {
ChooseAccountCaller, ConfirmSyncCaller, ShareTrackCaller, ConfirmDeleteCaller,
PlayMultipleCaller {
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
private static final String SEND_REQUEST_KEY = "send_request_key";
@@ -83,6 +81,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
protected static final int CAMERA_REQUEST_CODE = 5;
private SendRequest sendRequest;
private CheckPermissionAsyncTask asyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -90,6 +89,19 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
if (savedInstanceState != null) {
sendRequest = savedInstanceState.getParcelable(SEND_REQUEST_KEY);
}
Object retained = getLastCustomNonConfigurationInstance();
if (retained instanceof CheckPermissionAsyncTask) {
asyncTask = (CheckPermissionAsyncTask) retained;
asyncTask.setActivity(this);
}
}
@Override
public Object onRetainCustomNonConfigurationInstance() {
if (asyncTask != null) {
asyncTask.setActivity(null);
}
return asyncTask;
}
@Override
@@ -191,18 +203,20 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
}
if (needDrivePermission) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.DRIVE_SCOPE);
getSupportFragmentManager().beginTransaction()
.add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
startCheckPermission(SendToGoogleUtils.DRIVE_SCOPE);
} else {
onDrivePermissionSuccess();
}
}
}
@Override
public void onCheckPermissionDone(String scope, boolean success, Intent intent) {
private void startCheckPermission(String scope) {
asyncTask = new CheckPermissionAsyncTask(this, sendRequest.getAccount().name, scope);
asyncTask.execute();
}
public void onCheckPermissionDone(String scope, boolean success, Intent userRecoverableIntent) {
asyncTask = null;
if (success) {
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
onDrivePermissionSuccess();
@@ -212,7 +226,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
onSpreadsheetsPermissionSuccess();
}
} else {
if (intent != null) {
if (userRecoverableIntent != null) {
int requestCode;
if (scope.equals(SendToGoogleUtils.DRIVE_SCOPE)) {
requestCode = DRIVE_REQUEST_CODE;
@@ -221,7 +235,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
} else {
requestCode = SPREADSHEETS_REQUEST_CODE;
}
startActivityForResult(intent, requestCode);
startActivityForResult(userRecoverableIntent, requestCode);
} else {
onPermissionFailure();
}
@@ -271,10 +285,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
private void onMapsPermissionSuccess() {
// Check Fusion Tables permission
if (sendRequest.isSendFusionTables()) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.FUSION_TABLES_SCOPE);
getSupportFragmentManager()
.beginTransaction().add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
startCheckPermission(SendToGoogleUtils.FUSION_TABLES_SCOPE);
} else {
onFusionTablesSuccess();
}
@@ -283,10 +294,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
private void onFusionTablesSuccess() {
// Check Spreadsheets permission
if (sendRequest.isSendSpreadsheets()) {
Fragment fragment = CheckPermissionFragment.newInstance(
sendRequest.getAccount().name, SendToGoogleUtils.SPREADSHEETS_SCOPE);
getSupportFragmentManager()
.beginTransaction().add(fragment, CheckPermissionFragment.CHECK_PERMISSION_TAG).commit();
startCheckPermission(SendToGoogleUtils.SPREADSHEETS_SCOPE);
} else {
onSpreadsheetsPermissionSuccess();
}
@@ -1,133 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import java.io.IOException;
/**
* A non UI fragment to check permission.
*
* @author Jimmy Shih
*/
public class CheckPermissionFragment extends Fragment {
/**
* Interface for caller of this fragment.
*
* @author Jimmy Shih
*/
public interface CheckPermissionCaller {
/**
* Called when check permission is done.
*
* @param scope the permission scope
* @param success true if success
* @param intent if not success, intent to prompt for permission
*/
public void onCheckPermissionDone(String scope, boolean success, Intent intent);
}
public static final String CHECK_PERMISSION_TAG = "checkPermission";
private static final String TAG = CheckPermissionFragment.class.getSimpleName();
private static final String KEY_ACCOUNT_NAME = "accountName";
private static final String KEY_SCOPE = "scope";
private CheckPermissionCaller caller;
public static CheckPermissionFragment newInstance(String accountName, String scope) {
Bundle bundle = new Bundle();
bundle.putString(KEY_ACCOUNT_NAME, accountName);
bundle.putString(KEY_SCOPE, scope);
CheckPermissionFragment checkPermissionFragment = new CheckPermissionFragment();
checkPermissionFragment.setArguments(bundle);
return checkPermissionFragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
caller = (CheckPermissionCaller) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() + " must implement " + CheckPermissionCaller.class.getSimpleName());
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Only want one instance
setRetainInstance(true);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
String accountName = getArguments().getString(KEY_ACCOUNT_NAME);
String scope = getArguments().getString(KEY_SCOPE);
try {
SendToGoogleUtils.getGoogleAccountCredential(getActivity(), accountName, scope);
finish(scope, true, null);
} catch (UserRecoverableAuthException e) {
Intent intent = null;
try {
// HACK: UserRecoverableAuthException.getIntent can throw a null pointer exception.
intent = e.getIntent();
} catch (Exception e1) {
Log.e(TAG, "Exception in getIntent", e1);
}
finish(scope, false, intent);
} catch (GoogleAuthException e) {
Log.e(TAG, "GoogleAuthException", e);
finish(scope, false, null);
} catch (UserRecoverableAuthIOException e) {
finish(scope, false, e.getIntent());
} catch (IOException e) {
Log.e(TAG, "IOException", e);
finish(scope, false, null);
}
}
});
thread.start();
}
private void finish(final String scope, final boolean success, final Intent intent) {
getFragmentManager().popBackStack();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
caller.onCheckPermissionDone(scope, success, intent);
}
});
}
}
@@ -0,0 +1,134 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.tasks;
import com.google.android.apps.mytracks.AbstractSendToGoogleActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import java.io.IOException;
/**
* An async task to check permission.
*
* @author Jimmy Shih
*/
public class CheckPermissionAsyncTask extends AsyncTask<Void, Void, Boolean> {
private static final String TAG = CheckPermissionAsyncTask.class.getSimpleName();
private AbstractSendToGoogleActivity activity;
private final String accountName;
private final String scope;
/**
* True if the AsyncTask result is success.
*/
private boolean success;
/**
* User recoverable intent if failed.
*/
private Intent userRecoverableIntent;
/**
* True if the AsyncTask has completed.
*/
private boolean completed;
/**
* True if can retry the AsyncTask.
*/
private boolean canRetry;
public CheckPermissionAsyncTask(
AbstractSendToGoogleActivity activity, String accountName, String scope) {
this.activity = activity;
this.accountName = accountName;
this.scope = scope;
success = false;
userRecoverableIntent = null;
completed = false;
canRetry = true;
}
public void setActivity(AbstractSendToGoogleActivity activity) {
this.activity = activity;
if (completed && activity != null) {
activity.onCheckPermissionDone(scope, success, userRecoverableIntent);
}
}
@Override
protected Boolean doInBackground(Void... params) {
return performTask();
}
@Override
protected void onPostExecute(Boolean result) {
success = result;
completed = true;
if (activity != null) {
activity.onCheckPermissionDone(scope, success, userRecoverableIntent);
}
}
private boolean performTask() {
try {
SendToGoogleUtils.getGoogleAccountCredential(activity, accountName, scope);
return true;
} catch (UserRecoverableAuthException e) {
try {
// HACK: UserRecoverableAuthException.getIntent can throw a null pointer
// exception.
userRecoverableIntent = e.getIntent();
return false;
} catch (Exception e1) {
Log.e(TAG, "Exception in getIntent", e1);
userRecoverableIntent = null;
return retryTask();
}
} catch (GoogleAuthException e) {
Log.e(TAG, "GoogleAuthException", e);
return retryTask();
} catch (UserRecoverableAuthIOException e) {
userRecoverableIntent = e.getIntent();
return false;
} catch (IOException e) {
Log.e(TAG, "IOException", e);
return retryTask();
}
}
private boolean retryTask() {
if (isCancelled()) {
return false;
}
if (canRetry) {
canRetry = false;
return performTask();
}
return false;
}
}