Android的Google+的整合​​ - 重复UserRecoverableAuthException [英] Android Google+ integration - repeated UserRecoverableAuthException

查看:237
本文介绍了Android的Google+的整合​​ - 重复UserRecoverableAuthException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们已经联系了谷歌这件事,我们都在聊天

这个问题似乎是固定的设备的除了三星手机。

我加入了Google+登录的选项,每<一个一个应用程序href="https://developers.google.com/+/mobile/android/sign-in#server-side_access_for_your_app">official说明。一旦用户选择了他们的帐户,我想我的服务器去取回自己的Google+个人资料信息,并更新我们的网站,以配合他们的个人资料。

第一部分 - 让用户选择在本地一个谷歌帐户 - 似乎工作得很好。当我尝试请求令牌选定帐户中,谷歌身份验证使用适当的参数对话框显示;然而,使用该对话框,并重新请求令牌时,我授权的应用程序, GoogleAuthUtil.getToken(...)再次抛出一个 UserRecoverableAuthException NeedPermission ,不是 GooglePlayServicesAvailabilityException ),我也得到了同样的对话框,要求我批准!

此行为是对三星S3 present运行Android 4.1.1(3谷歌帐户)和运行4.0.3的宏碁A100。它不是在一个HTC冰川运行2.3.4 present。取而代之的是,HTC冰川给了我一个有效的身份验证code。所有设备都有谷歌的最新小游戏安装服务,并使用不同的Google+账号。

人见过这个?我可以在哪里开始调试?

下面是完整的code? - 是什么,显然歪曲

 公共类MyGooglePlusClient {
私有静态最后弦乐LOG_TAG =GPlus;
私有静态最后弦乐SCOPES_LOGIN = Scopes.PLUS_LOGIN ++ Scopes.PLUS_PROFILE;
私有静态最后弦乐ACTIVITIES_LOGIN =htt​​p://schemas.google.com/AddActivity;
私有静态MyGooglePlusClient myGPlus = NULL;
私人BaseActivity mRequestingActivity = NULL;
私人字符串mSelectedAccount = NULL;

/ **
 *获取GPlus单
 * @返回GPlus
 * /
公共同步静态MyGooglePlusClient的getInstance(){
    如果(myGPlus == NULL)
        myGPlus =新MyGooglePlusClient();
    返回myGPlus;
}

公共布尔登录(BaseActivity请求者){
    Log.w(LOG_TAG,开始登录......);
    如果(mRequestingActivity!= NULL){
        Log.w(LOG_TAG,登录尝试已在进行中。);
        返回false; //无法启动一个新的请求;已经进行
    }

    mRequestingActivity =请求;
    如果(mSelectedAccount == NULL){
        意向意图= AccountPicker.newChooseAccountIntent(NULL,NULL,新的String [] {} GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE,假的,
                空,GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE,NULL,NULL);
        mRequestingActivity.startActivityForResult(意向,BaseActivity.REQUEST_GPLUS_SELECT);
    }
    返回true;
}

公共无效loginCallback(字符串帐户名){
    mSelectedAccount =帐户名;
    authorizeCallback();
}

公共无效退出(){
    Log.w(LOG_TAG,注销...);
    mSelectedAccount = NULL;
}

公共无效authorizeCallback(){
    Log.w(LOG_TAG,用户授权);

    AsyncTask的&LT;虚空,虚空,字符串&GT;任务=新的AsyncTask&LT;虚空,虚空,字符串&GT;(){
        @覆盖
        保护字符串doInBackground(空... PARAMS){
            字符串标记= NULL;
            尝试 {
                叠B =新包();
                b.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,ACTIVITIES_LOGIN);
                令牌= GoogleAuthUtil.getToken(mRequestingActivity,
                        mSelectedAccount,
                        oauth2:服务器:CLIENT_ID:+ Constants.GOOGLE_PLUS_SERVER_OAUTH_CLIENT
                        +:api_scope:+ SCOPES_LOGIN,
                        B);
            }赶上(IOException异常transientEx){
                //网络或服务器错误,请稍后重
                Log.w(LOG_TAG,transientEx.toString());
                onCompletedLoginAttempt(假);
            }赶上(GooglePlayServicesAvailabilityException E){
                Log.w(LOG_TAG,谷歌播放不提供服务。);
                意图恢复= e.getIntent();
                mRequestingActivity.startActivityForResult(恢复,BaseActivity.REQUEST_GPLUS_AUTHORIZE);
            }赶上(UserRecoverableAuthException E){
                //恢复(与e.getIntent())
                Log.w(LOG_TAG,用户必须批准+ e.toString());
                意图恢复= e.getIntent();
                mRequestingActivity.startActivityForResult(恢复,BaseActivity.REQUEST_GPLUS_AUTHORIZE);
            }赶上(GoogleAuthException authEx){
                //电话不意想不到的成功
                Log.w(LOG_TAG,authEx.toString());
                onCompletedLoginAttempt(假);
            }

            Log.w(LOG_TAG,处理完任务,标记为+令牌);
            如果(令牌!= NULL){
                authorizeCallback(标记);
            }

            返回令牌;
        }

    };
    task.execute();
}

公共无效authorizeCallback(字符串标记){
    Log.w(LOG_TAG,令牌获得:+令牌);
    //&LT;剪断 - 做一些更多的东西,涉及连接到服务器,并在本地及GT复位状态;
}

公共无效onCompletedLoginAttempt(布尔成功){
    Log.w(?LOG_TAG,登录尝试+(成功得手:失败));
    mRequestingActivity.hideProgressDialog();
    mRequestingActivity = NULL;
}
}
 

解决方案

我已经有一阵子了这个问题,并想出了一个妥善的解决办法。

 字符串标记= GoogleAuthUtil.getToken(这一点,帐户名,scopeString,appActivities);
 

这行要么返回一次性令牌或将触发UserRecoverableAuthException。 在谷歌加号指南,它说,打开正确的恢复活动。

  startActivityForResult(e.getIntent(),RECOVERABLE_REQUEST_ code);
 

在活动返回的结果,它会带回来一些额外的意图,那就是新的令牌所在:

  @覆盖
保护无效onActivityResult(INT申请code,INT响应code,意图意图){
    如果(要求code == RECOVERABLE_REQUEST_ code和;&安培;响应code == RESULT_OK){
        捆绑额外= intent.getExtras();
        串oneTimeToken = extra.getString(的authToken);
    }
}
 

通过从额外提供的新oneTimeToken,您可以提交到服务器,以正确连接。

我希望这有助于!

We have contacted Google about this and we are on chat

The issue seems to be fixed for devices except Samsung phones.

I'm adding a Google+ sign in option to an app per the official instructions. 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.

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, GoogleAuthUtil.getToken(...) again throws a UserRecoverableAuthException (NeedPermission, not GooglePlayServicesAvailabilityException) and I get the same dialog asking me to approve!

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. All devices have the latest iteration of Google Play Services installed and are using different Google+ accounts.

Anyone seen this before? Where can I start with debugging?

Here's the complete code - is anything obviously awry?

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

解决方案

I've had this issue for a while and came up with a proper solution.

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

This line will either return the one time token or will trigger the UserRecoverableAuthException. On the Google Plus Sign In guide, it says to open the proper recovery activity.

startActivityForResult(e.getIntent(), RECOVERABLE_REQUEST_CODE);

When the activity returns with the result, it will come back with few extras in the intent and that is where the new token resides :

@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");
    }
}

With the new oneTimeToken given from the extra, you can submit to the server to connect properly.

I hope this helps!

这篇关于Android的Google+的整合​​ - 重复UserRecoverableAuthException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆