Reputation: 2495
I'm working on an app that uses Google Drive as a backend. I've run through the DrEdit example and I'm having issues with the authorization. I get to the point where I get a UserRecoverableAuthException
and use it to post a notification that the user has to do something. The problem is that nothing seems to happen when I click that notification.
I say nothing 'appears' to happen because it looks like Google Play is launching to handle it, it's just invisible. If I hit the app switch button I can see the Google Play services tile with a translucent background, but the user never sees the auth screen.
Is there something I'm missing? I have a project in that APIs console configured with drive access and the keys for both my release and develop builds added.
Here's the code I'm using for the notification. It's pretty much exactly what's in the DrEdit sample (which also has the same problem).
try {
GoogleAccountCredential credential =
GoogleAccountCredential.usingOAuth2(mContext, DriveScopes.DRIVE_FILE);
credential.setSelectedAccountName(mAccount.name);
// Trying to get a token right away to see if we are authorized
credential.getToken();
mService = new Drive.Builder(AndroidHttp.newCompatibleTransport(),
new GsonFactory(), credential).build();
} catch (UserRecoverableAuthException e) {
Log.e("Failed to get token");
// If the exception is User Recoverable, we display a notification that will trigger the
// intent to fix the issue.
Log.e("Notifying with intent: " + e.getIntent().toString());
NotificationManager notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent authorizationIntent = e.getIntent();
authorizationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).addFlags(
Intent.FLAG_FROM_BACKGROUND);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
authorizationIntent, 0);
Notification notification = new Notification.Builder(mContext)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setTicker("Permission requested")
.setContentTitle("Permission requested")
.setContentText("for account " + mAccount.name)
.setContentIntent(pendingIntent).setAutoCancel(true).build();
notificationManager.notify(0, notification);
} catch (Exception e) {
e.printStackTrace();
}
I just wanted to clarify that I do have a Google APIs project setup with access to the Drive API (was initially Drive SDK, but I fixed that) and my debug key for my app fetched with keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
. Still no luck.
Upvotes: 2
Views: 2450
Reputation: 2495
I've finally figured this one out. It looks like the docs and sample are a bit outdated, because just having DriveScopes.DRIVE_FILE
for the scope isn't enough, it needs to be prepended with "oauth:"
.
Here's my code:
try {
// Trying to get a token right away to see if we are authorized
GoogleAuthUtil.getTokenWithNotification(mContext, mAccount.name,
"oauth2:" + DriveScopes.DRIVE_FILE, null, mAuthority, mSyncBundle);
} catch (UserRecoverableNotifiedException e) {
Log.e("Failed to get token but notified user");
return null;
} catch (Exception e) {
Log.e("Failed to get token", e);
return null;
}
try {
GoogleAccountCredential credential =
GoogleAccountCredential.usingOAuth2(mContext, DriveScopes.DRIVE_FILE);
credential.setSelectedAccountName(mAccount.name);
...
Note: I also decided to switch to GoogleAuthUtil.getTokenWithNotification
to let the library handle the notification for me and restart the sync adapter when it's complete.
Upvotes: 3
Reputation: 12149
Here is the getDriveService method I used. (copied from rharter's response)
private Drive getDriveService() {
if (mService == null) {
try {
// Trying to get a token right away to see if we are authorized
GoogleAuthUtil.getTokenWithNotification(mContext,
mAccount.name, "oauth2:" + DriveScopes.DRIVE_FILE,
null);//, mAuthority, mSyncBundle);
}
catch (Exception e) {
Log.e(TAG, "error can't get token GREG GREG GREG", e);
return null;
}
try {
GoogleAccountCredential credential =
GoogleAccountCredential.usingOAuth2(mContext, DriveScopes.DRIVE_FILE);
credential.setSelectedAccountName(mAccount.name);
// Trying to get a token right away to see if we are authorized
credential.getToken();
mService = new Drive.Builder(AndroidHttp.newCompatibleTransport(),
new GsonFactory(), credential).build();
} catch (Exception e) {
Log.e(TAG, "Failed to get token");
// If the Exception is User Recoverable, we display a notification that will trigger the
// intent to fix the issue.
if (e instanceof UserRecoverableAuthException) {
UserRecoverableAuthException exception = (UserRecoverableAuthException) e;
NotificationManager notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent authorizationIntent = exception.getIntent();
authorizationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).addFlags(
Intent.FLAG_FROM_BACKGROUND);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
authorizationIntent, 0);
Notification notification = new Notification.Builder(mContext)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setTicker("Permission requested")
.setContentTitle("Permission requested")
.setContentText("for account " + mAccount.name)
.setContentIntent(pendingIntent).setAutoCancel(true).build();
notificationManager.notify(0, notification);
} else {
e.printStackTrace();
}
}
}
return mService;
}
Upvotes: 2
Reputation: 312
Make sure you had registered the signature you're signing your application correctly on the APIs console. We had a similar problem with our application, and fixing the signature footprint fixed our problem.
Upvotes: 0