If a user who is prompted to let my app access their Google Drive account hits "cancel," is there a way to acknowledge that they clicked cancel? Right now my application continuously asks them to choose a Google Drive account to use.
This is the code:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This is the XML for this activity
setContentView(R.layout.view_all_timelines_activity);
// This is used for authentication and uploading to Google Drive
googleApiClient = new GoogleApiClient.Builder(this).addApi(Drive.API)
.addScope(Drive.SCOPE_FILE).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
googleApiClient.connect();
How can I acknowledge if they say "Cancel" and don't want to connect? I don't want to constantly pester the user to log in.
I will try to elaborate a little deeper, so the answer covers the full process involved in getting the Google Drive Android API (GDAA) connected and working. Assuming you registered your app in the console, your app has to get through 3 hurdles. All of them involve your activity relinquishing control to another activity (dialog) and catching the result in callbacks. I attempted to write a small, lean and mean demo which can be found here. As usually, I failed miserably, the code ended up nothing close to lean&mean (more like bloated and ugly :).
I noticed that a lot of developers stumble on authorization/authentication. It needs to be stressed out that the 'console' has to know the app's package name and it's SHA1. The SHA1 of your app is contained inside of your *.APK file. You have 2 versions of APK files, the debug and the release version, each of them has a different SHA1. It was discussed here.
So, the hurdles are:
1/ Check Play Services
somewhere in OnCreate(), you may put an initial check if you have Google Play Services available and if your version is OK.
@Override
protected void onCreate(Bundle bundle) { super.onCreate(bundle);
...
if (checkPlayServices() && checkUserAccount()) {
GooDrive.init(this, UT.AM.getActiveEmil());
GooDrive.connect(true);
}
...
}
it is the 'checkPlayServices()' above, and goes like this
private boolean checkPlayServices() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (status != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
errorDialog(status, REQ_RECOVER);
} else {
finish();
}
return false;
}
return true;
}
If unsuccessful (but recoverable), the control is relinquished to GooPlaySvcs dialog, eventually resulting in the 'onActivityResult' callback REQ_RECOVER:
@Override
protected void onActivityResult(int request, int result, Intent data) {
switch (request) {
case REQ_RECOVER: {
mIsInAuth = false;
if (result == Activity.RESULT_OK) {
GooDrive.connect(true);
} else if (result == RESULT_CANCELED) {
finish();
}
break;
}
}
super.onActivityResult(request, result, data);
}
if the recovery is successful and user did not quit, the app can merrily continue to a connect attempt which may (or may not) be successful (we'll see later);
2/ Get the user account.
You will need user account (gmail), Google Drive will not talk to you without it. There are few ways to get it, you may hardcode it "myown@gmail.com", or you can go a get it from your device's list of accounts via Account Picker Dialog:
private boolean checkUserAccount() {
String email = UT.AM.getActiveEmil();
Account accnt = UT.AM.getPrimaryAccnt(true);
if (email == null) {
if (accnt == null) { // multiple or no accounts available, go pick/create one
accnt = UT.AM.getPrimaryAccnt(false); // pre-select primary account if present
Intent it = AccountPicker.newChooseAccountIntent(accnt, null,
new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null
);
startActivityForResult(it, REQ_ACCPICK);
return false; //--------------------->>>
} else { // there's only one goo account registered with the device, skip the picker
UT.AM.setEmil(accnt.name);
}
return true; //------------------>>>>
}
// UNLIKELY BUT POSSIBLE,
// emil's OK, but the account have been removed (through settings), re-select
accnt = UT.AM.getActiveAccnt();
if (accnt == null) {
accnt = UT.AM.getPrimaryAccnt(false);
Intent it = AccountPicker.newChooseAccountIntent(accnt, null,
new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null
);
startActivityForResult(it, REQ_ACCPICK);
return false; //------------------>>>
}
return true;
}
the code above gets gmail account from cache or the device's list of accounts, taking in account the possibility that the user removed the account in settings when the app was running. It works in cooperation with the AM(AccountManager) that caches previously selected account. Again, it may eventually end up in Account Picker Dialog resulting in a callback (same as above):
@Override
protected void onActivityResult(int request, int result, Intent data) {
switch (request) {
case REQ_ACCPICK: { // return from account picker
if (result == Activity.RESULT_OK && data != null) {
String email = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (UT.AM.setEmil(email) == UT.AM.CHANGED) {
GooDrive.init(this, UT.AM.getActiveEmil());
GooDrive.connect(true);
}
} else if (UT.AM.getActiveEmil() == null) {
finish();
}
break;
}
}
super.onActivityResult(request, result, data);
}
If the user did not quit, the app can cheerfully initialize GoogleApiClient and make another connect attempt which may (or may not) be successful;
3/ The connect attempt may result in onConnectionFailed(), which may have recovery solution
@Override
public void onConnectionFailed(ConnectionResult result) {
if (!mIsInAuth) {
if (result.hasResolution()) {
try {
mIsInAuth = true;
result.startResolutionForResult(this, REQ_AUTH);
} catch (IntentSender.SendIntentException e) {
finish();
}
} else {
finish();
}
}
}
if it has a solution, it is likely the need for user authorization. Basically user confirming that this app can have a party with Google Drive. And again, the result comes back in onActivityResult callback.
@Override
protected void onActivityResult(int request, int result, Intent data) {
switch (request) {
case REQ_AUTH: {
mIsInAuth = false;
if (result == RESULT_OK) {
GooDrive.connect(true);
} else if (result == RESULT_CANCELED) {
finish();
}
break;
}
}
super.onActivityResult(request, result, data);
}
The code here is the same as in step 1/, i.e. connect on success, quit o failure / user CANCEL. Google Drive remembers this authorization, so you usually see it only once. If you need to reset it, go to the web Drive, Settings > Manage Apps > Disconnect from Drive
RECAP:
- Step 1: If you don't get through hurdle one, you are DOA.
- Step 2: If you have only one account or user selected one already and you cached it, hand it to GooDrive initialization without bugging the user.
- Step 3: If the user authorized the app, it will never bug him again, unless he/she messes with 'Disconnect from Drive' on the web.
The steps 2 and 3 may not come in the order described here, it depends on your app logic.
Good Luck.
来源:https://stackoverflow.com/questions/28439129/how-to-acknowledge-when-user-doesnt-want-to-connect-to-google-play-services