rharter
rharter

Reputation: 2495

Google Play Services: TokenActivity appears empty when asking for auth

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.

App Switcher

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();
}

Edit:

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

Answers (3)

rharter
rharter

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

gregm
gregm

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

peter
peter

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

Related Questions