Android Google+ 統合 - UserRecoverableAuthException が繰り返される 質問する

Android Google+ 統合 - UserRecoverableAuthException が繰り返される 質問する

この件についてGoogleに連絡したところ、私たちはチャット中です

この問題はデバイスでは修正されているようですを除外するサムスンの携帯電話。

私はアプリにGoogle+のサインインオプションを追加しています。公式指示ユーザーがアカウントを選択したら、サーバーでそのユーザーの Google+ プロフィール情報を取得し、それに合わせて当サイトのプロフィールを更新したいと思います。

最初の部分、つまりユーザーにローカルで Google アカウントを選択させる部分は、問題なく機能しているようです。選択したアカウントのトークンをリクエストしようとすると、適切なパラメータを含む Google 認証ダイアログが表示されます。ただし、そのダイアログを使用してアプリを承認し、トークンを再度リクエストすると、GoogleAuthUtil.getToken(...)再びUserRecoverableAuthException(NeedPermissionではなくGooglePlayServicesAvailabilityException) がスローされ、承認を求める同じダイアログが表示されます。

この動作は、Android 4.1.1 を実行している Samsung S3 (3 つの Google アカウントを使用) と 4.0.3 を実行している Acer A100 で発生します。2.3.4 を実行している HTC Glacier では発生しません。代わりに、HTC Glacier は有効な認証コードを提供します。すべてのデバイスには最新の Google Play 開発者サービスがインストールされており、異なる Google+ アカウントが使用されています。

これを見たことがある人はいますか? デバッグはどこから始めればよいでしょうか?

完全なコードは次のとおりです。明らかに何かおかしいところはありますか?

public class MyGooglePlusClient {
private static final String LOG_TAG = "GPlus";
private static final String SCOPES_LOGIN = Scopes.PLUS_LOGIN + " " + Scopes.PLUS_PROFILE;
private static final String ACTIVITIES_LOGIN = "http://schemas.google.com/AddActivity";
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, "Starting login...");
    if (mRequestingActivity != null) {
        Log.w(LOG_TAG, "Login attempt already in progress.");
        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, "Logging out...");
    mSelectedAccount = null;
}

public void authorizeCallback() {
    Log.w(LOG_TAG, "User authorized");

    AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @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,
                        "oauth2:server:client_id:"+Constants.GOOGLE_PLUS_SERVER_OAUTH_CLIENT
                        +":api_scope:" + 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, "Google Play services not available.");
                Intent recover = e.getIntent();
                mRequestingActivity.startActivityForResult(recover, BaseActivity.REQUEST_GPLUS_AUTHORIZE);
            } catch (UserRecoverableAuthException e) {
                // Recover (with e.getIntent())
                Log.w(LOG_TAG, "User must approve "+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, "Finished with task; token is "+token);
            if (token != null) {
                authorizeCallback(token);
            }
            
            return token;
        }

    };
    task.execute();
}

public void authorizeCallback(String token) {
    Log.w(LOG_TAG, "Token obtained: "+token);
    // <snipped - do some more stuff involving connecting to the server and resetting the state locally>
}

public void onCompletedLoginAttempt(boolean success) {
    Log.w(LOG_TAG, "Login attempt "+(success ? "succeeded" : "failed"));
    mRequestingActivity.hideProgressDialog();
    mRequestingActivity = null;
}
}

ベストアンサー1

私はしばらくこの問題を抱えていましたが、適切な解決策を見つけました。

String token = GoogleAuthUtil.getToken(this, accountName, scopeString, appActivities);

この行は、ワンタイム トークンを返すか、UserRecoverableAuthException をトリガーします。Google Plus サインイン ガイドでは、適切な回復アクティビティを開くように指示されています。

startActivityForResult(e.getIntent(), RECOVERABLE_REQUEST_CODE);

アクティビティが結果を返すと、インテント内にいくつかの追加情報が返され、そこに新しいトークンが存在します。

@Override
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
    if (requestCode == RECOVERABLE_REQUEST_CODE && responseCode == RESULT_OK) {
        Bundle extra = intent.getExtras();
        String oneTimeToken = extra.getString("authtoken");
    }
}

エクストラから与えられた新しい oneTimeToken を使用して、サーバーに送信し、適切に接続できます。

これが役に立つことを願っています!

おすすめ記事