静默登录以使用GoogleApiClient检索令牌 [英] Silent sign in to retrieve token with GoogleApiClient

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

问题描述

我在我的应用中使用"Google登录".因此,我使用GoogleApiClient类获取后端所需的用户电子邮件和ID令牌.

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.

用户登录后,便可以访问一个活动(当然),并且可以使用该活动让GoogleApiClient通过调用来处理UI生命周期中的内容 builder.enableAutoManage(myActivity,...)

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, ...)

这很好.

但是,在以后的阶段(几天后),我需要获取一个新的令牌(由于某些原因,在这里我将不再赘述).我想得到这个令牌 无需用户交互即可静默地进行.但是,在我的代码中需要这个新令牌的时候,我无法访问任何Activity实例.这意味着我无法 进行上述呼叫,即"builder.enableAutoManage".而且我发现,如果我不打那个电话,那么静默登录似乎就行不通了.

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.

我已附上以下代码.现在,看看"silentLogin"方法.只要我作为用户实际登录时收到的令牌还不到一小时,则语句"pendingResult.isDone"将返回true,并且可以接收缓存的令牌.但是,如果我作为用户收到的令牌进行了实际登录,并且早于一小时,那么将调用"pendingResult.setResultCallback",但"onResult"方法将永远无法调用,而我将无法获得新的令牌.令牌.如果我从一个活动中做完全相同的事情,那么就不会发生此问题(并因此也将其称为"builder.enableAutoManage").

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?

我正在使用com.google.android.gms:play-services-auth:8.4.0

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

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 = "XXXXXXXXXXXXXXXXXXXXXXXX.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);
            }
        }
    }
}

推荐答案

是的,以上答案正确.通常,任何GoogleApiClient都必须先连接,然后才能返回您任何数据. enableAutoManage可帮助您在onStart()/onStop()期间自动调用connect()/disconnect().如果您不使用autoManage,则需要手动进行connect().

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.

更好的是,您应该在finally块中断开连接.

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

假设您不在UI线程上.

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

此外,还需要一点点清理代码: 1.通过以下配置构建的gso与上面粘贴的代码相同:

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. 根据您当前的逻辑,addOnConnectionFailedListener/addConnectionCallbacks除了adb日志外无济于事.也许只是将它们完全删除?

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

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