UserRecoverableAuthException: NeedPermission

后端 未结 6 626
醉酒成梦
醉酒成梦 2020-12-01 09:16

I tried to follow tutorial: https://developers.google.com/android/guides/http-auth.

Code:

token = GoogleAuthUtil.getToken(getApplicationContext(),
           


        
相关标签:
6条回答
  • 2020-12-01 09:39

    Try following the Drive quickstart for Android, it is a step-by-step guide showing how to authorize and upload a file to Drive: https://developers.google.com/drive/quickstart-android

    To be more specific, it looks like you are not catching the UserRecoverableException and triggering the intent to have the user authorize the app. This is documented in the Google Play Services docs you linked and handled in the quickstart sample as follows:

    ...
    } catch (UserRecoverableAuthIOException e) {
      startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
    }
    ... 
    
    0 讨论(0)
  • 2020-12-01 09:44

    On this docs page https://developers.google.com/+/mobile/android/sign-in the example has a good explanation for this exception.

    In particular, it looks like this line should be noted:

    Requesting an authorization code will always throw UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken

    catch (UserRecoverableAuthException e) {
      // Requesting an authorization code will always throw
      // UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
      // because the user must consent to offline access to their data.  After
      // consent is granted control is returned to your activity in onActivityResult
      // and the second call to GoogleAuthUtil.getToken will succeed.
      startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
      return;
    }
    
    0 讨论(0)
  • 2020-12-01 09:46

    the method getAndUseAuthTokenBlocking() of the official GoogleAuthUtil tutorial explains pretty well how to handle the exception:

    // Example of how to use the GoogleAuthUtil in a blocking, non-main thread context
       void getAndUseAuthTokenBlocking() {
           try {
              // Retrieve a token for the given account and scope. It will always return either
              // a non-empty String or throw an exception.
              final String token = GoogleAuthUtil.getToken(Context, String, String)(context, email, scope);
              // Do work with token.
              ...
              if (server indicates token is invalid) {
                  // invalidate the token that we found is bad so that GoogleAuthUtil won't
                  // return it next time (it may have cached it)
                  GoogleAuthUtil.invalidateToken(Context, String)(context, token);
                  // consider retrying getAndUseTokenBlocking() once more
                  return;
              }
              return;
           } catch (GooglePlayServicesAvailabilityException playEx) {
             Dialog alert = GooglePlayServicesUtil.getErrorDialog(
                 playEx.getConnectionStatusCode(),
                 this,
                 MY_ACTIVITYS_AUTH_REQUEST_CODE);
             ...
           } catch (UserRecoverableAuthException userAuthEx) {
              // Start the user recoverable action using the intent returned by
              // getIntent()
              myActivity.startActivityForResult(
                      userAuthEx.getIntent(),
                      MY_ACTIVITYS_AUTH_REQUEST_CODE);
              return;
           } catch (IOException transientEx) {
              // network or server error, the call is expected to succeed if you try again later.
              // Don't attempt to call again immediately - the request is likely to
              // fail, you'll hit quotas or back-off.
              ...
              return;
           } catch (GoogleAuthException authEx) {
              // Failure. The call is not expected to ever succeed so it should not be
              // retried.
              ...
              return;
           }
       }
    0 讨论(0)
  • 2020-12-01 09:47

    I found the answers here are passive solutions and not preventive.
    According to my very short experience, UserRecoverableAuthException: NeedPermission will be thrown in the following 3 cases:

    #1 Appropriate Scope is not requested when signing in to Google

    Check that the scopes you are requesting are correct. Android should ask the user to allow permission after the authentication process via permission request dialog. This will prevent UserRecoverableAuthException when calling API.

    GoogleSignInOptions o = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestScopes(new Scope(DriveScopes.DRIVE)) // request permission for Drive API
                .requestScopes(new Scope(SheetsScopes.SPREADSHEETS)) // request permission for Sheets API
                .requestEmail()
                .build();
    

    #2 User has denied permission

    The user has pushed "DENY" button on permission request dialog.

    #3 User has rejected permissions from your app

    As for Android 8.1.x, there is a menu where you can reject permissions for individual apps. Not sure about other versions, though.

    Settings > Google > Connected apps
    

    UserRecoverableAuthException thrown by #2 and #3 is unavoidable because those are the result of user activity. But isn't that meaningless to show permission request dialog again with below code despite the user's rejection?

    } catch (UserRecoverableAuthIOException e) {
      startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
    }
    
    0 讨论(0)
  • 2020-12-01 09:56

    I had the same error, in my case I was using a wrong scope, I just change

    https://www.googleapis.com/auth/plus.login
    

    for

    https://www.googleapis.com/auth/userinfo.profile
    
    0 讨论(0)
  • 2020-12-01 10:02

    The docs have been recently updated and now work to support SDK M(requesting permission) and also show the OAuth dialog.

    NOTE Google Docs are often not up to date but they seem to pay attention when you report an issue. The example was updated with a week of me sending a feedback. So if you see a non-working example, send feedback!

    https://developers.google.com/drive/v3/web/quickstart/android

    0 讨论(0)
提交回复
热议问题