沉默登录中检索令牌GoogleApiClient [英] Silent sign in to retreive token with GoogleApiClient

查看:1178
本文介绍了沉默登录中检索令牌GoogleApiClient的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用谷歌登录。因此,我使用类GoogleApiClient来获取用户的电子邮件和ID令牌,我需要对我的后端。

当在用户登录,那么我可以访问(当然)一个活动,我用的活动,让GoogleApiClient通过调用处理UI的生命周期的东西
builder.enableAutoManage(myActivity,...)

这工作得很好。

然而,在后一阶段(几天后),我需要一个新的令牌(出于某种原因,我不会再进一步​​这里)。我想获得此令牌
静默无需用户交互。然而,在我的code的地步,我需要这个新的令牌我有任何活动实例的访问权限。这意味着,我不能
做出以上,即builder.enableAutoManage中提到的电话。而且我发现,如果我不要做这样很电话,然后沉默登录似乎并没有工作。

我附上下面的code。现在,走在silentLogin的方法看看。只要在用户中做了实际的标志,我收到了令牌,是年龄小于一小时后,语句pendingResult.isDone将返回true,并可以接收缓存的令牌。但是,如果因为用户没有在实际的标志,我收到了令牌,早于一小时后,电话pendingResult.setResultCallback制作,但一个onResult方法不会被调用,我不能得到一个新的令牌。如果我做一项活动如出一辙此问题不会发生(并也进行呼叫builder.enableAutoManage)。

所以,没有任何人知道我在做什么错的,更重要的是 - 如何解决这个问题,并得到一个新的令牌不访问活动实例

我使用com.google.android.gms:发挥服务-auth的:8.4.0

谢谢
奥拉

 包com.google.samples.quickstart.signin;进口android.content.Context;
进口android.os.Bundle;
进口android.util.Log;进口com.google.android.gms.auth.api.Auth;
进口com.google.android.gms.auth.api.signin.GoogleSignInAccount;
进口com.google.android.gms.auth.api.signin.GoogleSignInOptions;
进口com.google.android.gms.auth.api.signin.GoogleSignInResult;
进口com.google.android.gms.common.ConnectionResult;
进口com.google.android.gms.common.Scopes;
进口com.google.android.gms.common.api.GoogleApiClient;
进口com.google.android.gms.common.api.OptionalPendingResult;
进口com.google.android.gms.common.api.ResultCallback;
进口com.google.android.gms.common.api.Scope;/ **
 *使用这个类使用的OpenID OAuth的方法谷歌帐户登录。
 * /
公共类GoogleLoginStackOverflow {
    私有静态最后弦乐TAG = GoogleLoginIdToken.class.getName();
    私有静态最后弦乐SERVER_CLIENT_ID =292748398091-vn7g9iohtvb5l8371h7oqpeaaebhdaq9.apps.googleusercontent.com;    私人GoogleApiClient mGoogleApiClient;
    私人语境mContext;    私人GoogleLoginStackOverflow(上下文appContext){
        this.mContext = appContext;
        createGoogleClient();
    }    / **
     *在执行无声标志,并获取一个令牌。
     *
     * @参数appContext应用程序上下文
     * /
    公共静态无效silentLogin(上下文appContext){
        GoogleLoginStackOverflow googleLoginIdToken =新GoogleLoginStackOverflow(appContext);
        googleLoginIdToken.silentLogin();
    }    私人无效createGoogleClient(){
        GoogleSignInOptions GSO =新GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestProfile()
                .requestScopes(新范围(Scopes.PROFILE))
                .requestIdToken(SERVER_CLIENT_ID)
                .requestEmail()
                。建立();        mGoogleApiClient =新GoogleApiClient.Builder(mContext)
                .addOnConnectionFailedListener(新GoogleApiClient.OnConnectionFailedListener(){
                    @覆盖
                    公共无效onConnectionFailed(ConnectionResult connectionResult){
                        的System.out.println(onConnectionFailed =+ connectionResult);
                        onSilentLoginFinished(NULL);
                    }
                })
                .addConnectionCallbacks(新GoogleApiClient.ConnectionCallbacks(){
                    @覆盖
                    公共无效onConnected(束束){
                        的System.out.println(onConnected包=+包);
                        onSilentLoginFinished(NULL);
                    }                    @覆盖
                    公共无效onConnectionSuspended(int i)以{
                        的System.out.println(onConnectionSuspended我=+ I);
                        onSilentLoginFinished(NULL);
                    }
                })。addApi(Auth.GOOGLE_SIGN_IN_API,GSO)
                。建立();
    }    私人无效silentLogin(){
        OptionalPendingResult< GoogleSignInResult> pendingResult = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
        如果(pendingResult!= NULL){
            如果(pendingResult.isDone()){
                //如果用户的缓存凭据有效,则OptionalPendingResult将完成
                //和GoogleSignInResult将可瞬间。
                Log.d(TAG---------------- CACHED登录------------);
                的System.out.println(pendingResult做=);
                GoogleSignInResult signInResult = pendingResult.get();
                onSilentLoginFinished(signInResult);
            }其他{
                的System.out.println(设置结果回调);
                //如果用户没有previously本设备或登录上登录已过期,
                //这个异步分公司将试图在用户默默地签字。跨设备
                //单点登录将出现在该分支。
                pendingResult.setResultCallback(新ResultCallback< GoogleSignInResult>(){
                    @覆盖
                    公共无效onResult(GoogleSignInResult googleSignInResult){
                        的System.out.println(googleSignInResult =+ googleSignInResult);
                        onSilentLoginFinished(googleSignInResult);
                    }
                });
            }
        }其他{
            onSilentLoginFinished(NULL);
        }
    }    私人无效onSilentLoginFinished(GoogleSignInResult signInResult){
        的System.out.println(GoogleLoginIdToken.onSilentLoginFinished);
        如果(signInResult!= NULL){
            GoogleSignInAccount signInAccount = signInResult.getSignInAccount();
            如果(signInAccount!= NULL){
                字符串EMAILADDRESS = signInAccount.getEmail();
                字符串标记= signInAccount.getIdToken();
                的System.out.println(标记=+令牌);
                的System.out.println(EMAILADDRESS =+ EMAILADDRESS);
            }
        }
    }}


解决方案

是的,上面的回答是正确的。一般来说,任何GoogleApiClient需要连接之前,它可以返回你的任何数据。 enableAutoManage帮助您来电在onStart()/的onStop()中()/断开()自动连接。如果你不使用autoManage,你将需要手动连接()。

和更妙的是,你应该在finally块断开连接。

假设你是不是在UI线程上。

  {尝试
    ConnectionResult结果= mGoogleApiClient.blockingConnect();
    如果(result.isSuccess()){
        GoogleSignInResult googleSignInResult =
            Auth.GoogleSignInApi.silentSignIn(googleApiClient).await();
    ...
    }
} {最后
    mGoogleApiClient.disconnect();
}

和也,清理你的code一点点:
1. GSO从下面配置内置等同于你的粘贴$ C $上面C:

  GoogleSignInOptions GSO =
   新GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(SERVER_CLIENT_ID)
        .requestEmail()
        。建立();

<醇开始=2>

  • 根据您当前的逻辑,addOnConnectionFailedListener / addConnectionCallbacks不利于亚行比其他记录。也许只是完全删除它们?

  • I am using "Google Sign-In" in my app. Hence I use the class GoogleApiClient to get the user email and the ID token that I need for my backend.

    When the user signs in, then I have access to an Activity (of course) and I use that Activity to let the GoogleApiClient handle the UI lifecycle stuff by calling builder.enableAutoManage(myActivity, ...)

    This works fine.

    However, at a later stage (several days later), I need to get a new token (for some reason that I will not go into further here). I want to get this token silently without user interaction. However, at the point in my code where I need this new token I have no access to any Activity instance. That means that I am not able to make the call mentioned above i.e. "builder.enableAutoManage". And I have found that if I do not make that very call, then the silent login does not seem to work.

    I have attached the code below. Now, take a look in the "silentLogin" method. As long as the token that I have received as the user did the actual sign in, is younger than one hour, then the statement "pendingResult.isDone" will return true and the cached token can be received. However, if the token that I have received as the user did the actual sign in, is older than one hour, then the call "pendingResult.setResultCallback" is made BUT THE "onResult" method IS NEVER CALLED and I can not get a new token. This problem does not happen if I do exactly the same from an activity (and by that also make the call "builder.enableAutoManage").

    So, does anybody know what I am doing wrong and more importantly - how to solve this problem and get a new token without access to an activity instance?

    I am using com.google.android.gms:play-services-auth:8.4.0

    thanks Ola

    package com.google.samples.quickstart.signin;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.util.Log;
    
    import com.google.android.gms.auth.api.Auth;
    import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
    import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
    import com.google.android.gms.auth.api.signin.GoogleSignInResult;
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.Scopes;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.OptionalPendingResult;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Scope;
    
    /**
     * Use this class to login with google account using the OpenId oauth method.
     */
    public class GoogleLoginStackOverflow {
        private static final String TAG = GoogleLoginIdToken.class.getName();
        private static final String SERVER_CLIENT_ID = "292748398091-vn7g9iohtvb5l8371h7oqpeaaebhdaq9.apps.googleusercontent.com";
    
        private GoogleApiClient mGoogleApiClient;
        private Context mContext;
    
        private GoogleLoginStackOverflow(Context appContext) {
            this.mContext = appContext;
            createGoogleClient();
        }
    
        /**
         * Performs a silent sign in and fetch a token.
         *
         * @param appContext Application context
         */
        public static void silentLogin(Context appContext) {
            GoogleLoginStackOverflow googleLoginIdToken = new GoogleLoginStackOverflow(appContext);
            googleLoginIdToken.silentLogin();
        }
    
        private void createGoogleClient() {
            GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestProfile()
                    .requestScopes(new Scope(Scopes.PROFILE))
                    .requestIdToken(SERVER_CLIENT_ID)
                    .requestEmail()
                    .build();
    
            mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                    .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult connectionResult) {
                            System.out.println("onConnectionFailed  = " + connectionResult);
                            onSilentLoginFinished(null);
                        }
                    })
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(Bundle bundle) {
                            System.out.println("onConnected bundle = " + bundle);
                            onSilentLoginFinished(null);
                        }
    
                        @Override
                        public void onConnectionSuspended(int i) {
                            System.out.println("onConnectionSuspended i = " + i);
                            onSilentLoginFinished(null);
                        }
                    }).addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                    .build();
        }
    
        private void silentLogin() {
            OptionalPendingResult<GoogleSignInResult> pendingResult = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
            if (pendingResult != null) {
                if (pendingResult.isDone()) {
                    // If the user's cached credentials are valid, the OptionalPendingResult will be "done"
                    // and the GoogleSignInResult will be available instantly.
                    Log.d(TAG, " ----------------  CACHED SIGN-IN ------------");
                    System.out.println("pendingResult is done = ");
                    GoogleSignInResult signInResult = pendingResult.get();
                    onSilentLoginFinished(signInResult);
                } else {
                    System.out.println("Setting result callback");
                    // If the user has not previously signed in on this device or the sign-in has expired,
                    // this asynchronous branch will attempt to sign in the user silently.  Cross-device
                    // single sign-on will occur in this branch.
                    pendingResult.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                        @Override
                        public void onResult(GoogleSignInResult googleSignInResult) {
                            System.out.println("googleSignInResult = " + googleSignInResult);
                            onSilentLoginFinished(googleSignInResult);
                        }
                    });
                }
            } else {
                onSilentLoginFinished(null);
            }
        }
    
        private void onSilentLoginFinished(GoogleSignInResult signInResult) {
            System.out.println("GoogleLoginIdToken.onSilentLoginFinished");
            if (signInResult != null) {
                GoogleSignInAccount signInAccount = signInResult.getSignInAccount();
                if (signInAccount != null) {
                    String emailAddress = signInAccount.getEmail();
                    String token = signInAccount.getIdToken();
                    System.out.println("token = " + token);
                    System.out.println("emailAddress = " + emailAddress);
                }
            }
        }
    
    }
    

    解决方案

    Yes, answer above is correct. In general, any GoogleApiClient needs to be connected before it can return you any data. enableAutoManage helps you to call connect() / disconnect() automatically during onStart() / onStop(). If you don't use autoManage, you will need to connect() manually.

    And even better, you should disconnect in a finally block.

    Assuming you are not on the UI thread.

    try {
        ConnectionResult result = mGoogleApiClient.blockingConnect();
        if (result.isSuccess()) {
            GoogleSignInResult googleSignInResult =
                Auth.GoogleSignInApi.silentSignIn(googleApiClient).await();
        ...
        }
    } finally {
        mGoogleApiClient.disconnect();
    }
    

    And also, to clean up your code a little bit: 1. gso built from below configuration is identical to your pasted code above:

    GoogleSignInOptions gso =
       new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(SERVER_CLIENT_ID)
            .requestEmail()
            .build();
    

    1. Based on your current logic, addOnConnectionFailedListener / addConnectionCallbacks doesn't help other than adb log. Maybe just remove them completely?

    这篇关于沉默登录中检索令牌GoogleApiClient的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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