title: Android Google+ integration - repeated UserRecoverableAuthException
body: <p><em>We have contacted Google about this and <a href="https://chat.stackoverflow.com/rooms/33772/discussion-between-lee-and-arkaaito">we are on chat</a></em></p>
  <p><em>The issue seems to be fixed for devices <strong>except</strong> Samsung phones.</em></p>
  <p>I'm adding a Google+ sign in option to an app per the <a href="https://developers.google.com/+/mobile/android/sign-in#server-side_access_for_your_app" rel="nofollow noreferrer">official instructions</a>.  Once the user has selected their account I would like my server to retrieve their Google+ profile info and update their profile on our site to match.</p>
  <p>The first part - having the user select a Google account locally - seems to work just fine.  When I try to request a token for the selected account, the Google auth dialog displays with the appropriate parameters; however, when I authorize the app using that dialog and re-request the token, <code>GoogleAuthUtil.getToken(...)</code> again throws a <code>UserRecoverableAuthException</code> (<code>NeedPermission</code>, not <code>GooglePlayServicesAvailabilityException</code>) and I get the same dialog asking me to approve!</p>
  <p><strong>This behavior is present on a Samsung S3 running Android 4.1.1 (with 3 Google accounts) and an Acer A100 running 4.0.3.  It is NOT present on an HTC Glacier running 2.3.4.  Instead, the HTC Glacier gives me a valid auth code.</strong>  All devices have the latest iteration of Google Play Services installed and are using different Google+ accounts.</p>
  <p>Anyone seen this before?  Where can I start with debugging?</p>
  <p>Here's the complete code - is anything obviously awry?</p>
  <pre><code>public class MyGooglePlusClient {
  private static final String LOG_TAG = &quot;GPlus&quot;;
  private static final String SCOPES_LOGIN = Scopes.PLUS_LOGIN + &quot; &quot; + Scopes.PLUS_PROFILE;
  private static final String ACTIVITIES_LOGIN = &quot;http://schemas.google.com/AddActivity&quot;;
  private static MyGooglePlusClient myGPlus = null;
  private BaseActivity mRequestingActivity = null;
  private String mSelectedAccount = null;
      
  /**
   * Get the GPlus singleton
   * @return GPlus
   */
  public synchronized static MyGooglePlusClient getInstance() {
      if (myGPlus == null)
          myGPlus = new MyGooglePlusClient();
      return myGPlus;
  }
  
  public boolean login(BaseActivity requester) {
      Log.w(LOG_TAG, &quot;Starting login...&quot;);
      if (mRequestingActivity != null) {
          Log.w(LOG_TAG, &quot;Login attempt already in progress.&quot;);
          return false; // Cannot launch a new request; already in progress
      }
      
      mRequestingActivity = requester;
      if (mSelectedAccount == null) {
          Intent intent = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, false,
                  null, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE, null, null);
          mRequestingActivity.startActivityForResult(intent, BaseActivity.REQUEST_GPLUS_SELECT);
      }
      return true;
  }
  
  public void loginCallback(String accountName) {
      mSelectedAccount = accountName;
      authorizeCallback();
  }
      
  public void logout() {
      Log.w(LOG_TAG, &quot;Logging out...&quot;);
      mSelectedAccount = null;
  }
  
  public void authorizeCallback() {
      Log.w(LOG_TAG, &quot;User authorized&quot;);
  
      AsyncTask&lt;Void, Void, String&gt; task = new AsyncTask&lt;Void, Void, String&gt;() {
          @Override
          protected String doInBackground(Void... params) {
              String token = null;
              try {
                  Bundle b = new Bundle();
                  b.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES, ACTIVITIES_LOGIN);
                  token = GoogleAuthUtil.getToken(mRequestingActivity,
                          mSelectedAccount,
                          &quot;oauth2:server:client_id:&quot;+Constants.GOOGLE_PLUS_SERVER_OAUTH_CLIENT
                          +&quot;:api_scope:&quot; + SCOPES_LOGIN,
                          b);
              } catch (IOException transientEx) {
                  // Network or server error, try later
                  Log.w(LOG_TAG, transientEx.toString());
                  onCompletedLoginAttempt(false);
              } catch (GooglePlayServicesAvailabilityException e) {
                  Log.w(LOG_TAG, &quot;Google Play services not available.&quot;);
                  Intent recover = e.getIntent();
                  mRequestingActivity.startActivityForResult(recover, BaseActivity.REQUEST_GPLUS_AUTHORIZE);
              } catch (UserRecoverableAuthException e) {
                  // Recover (with e.getIntent())
                  Log.w(LOG_TAG, &quot;User must approve &quot;+e.toString());
                  Intent recover = e.getIntent();
                  mRequestingActivity.startActivityForResult(recover, BaseActivity.REQUEST_GPLUS_AUTHORIZE);
              } catch (GoogleAuthException authEx) {
                  // The call is not ever expected to succeed
                  Log.w(LOG_TAG, authEx.toString());
                  onCompletedLoginAttempt(false);
              }
  
              Log.w(LOG_TAG, &quot;Finished with task; token is &quot;+token);
              if (token != null) {
                  authorizeCallback(token);
              }
              
              return token;
          }
  
      };
      task.execute();
  }
  
  public void authorizeCallback(String token) {
      Log.w(LOG_TAG, &quot;Token obtained: &quot;+token);
      // &lt;snipped - do some more stuff involving connecting to the server and resetting the state locally&gt;
  }
  
  public void onCompletedLoginAttempt(boolean success) {
      Log.w(LOG_TAG, &quot;Login attempt &quot;+(success ? &quot;succeeded&quot; : &quot;failed&quot;));
      mRequestingActivity.hideProgressDialog();
      mRequestingActivity = null;
  }
  }
  </code></pre>