Android GoogleSignIn:同时使用多个帐户 + 失败时延迟登录

Android GoogleSignIn: Multiple accounts at the same time + deferred sign-in upon failure

我正在编写一个应用程序,它使用 Firebase 身份验证与我的后端服务器进行身份验证。

我提供 Google 登录和基于 Email/Password 的身份验证。 Email/Password 微不足道。

这是我使用 Google 登录的流程:

1) 我用 .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 创建了一个 mGoogleApiClient= new GoogleApiClient,其中 gso= GoogleSignInOptions.requestIdToken(...)).requestEmail()

2) 我调用 startActivityForResult(signInIntent, RC_GOOGLE_SIGN_IN); 其中 signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)

3) 在 onActivityResult 中我得到 result= Auth.GoogleSignInApi.getSignInResultFromIntent(data); 并从那里 GoogleSignInAccount account=result.getSignInAccount() 我最终通过调用 mFirebaseAuth.signInWithCredential(GoogleAuthProvider.getCredential([ 登录到 Firebase =80=]account.getIdToken(), null))

4) 然后我 "generate"/通过 fbUser.getToken(false) 检索一个 Firebase JWT,然后我将其发送到后端服务器给 create/authenticate 那边的用户。

4 个步骤有效。我能够将应用程序登录到 Firebase 和我的后端服务器。

如果我一次只想使用一个帐户,这很好。实际上,这就是我想要做的,但是我的问题如下:

我想像 Gmail 或 Inbox 一样,提供通过上述 4 个步骤至少登录过一次的帐户列表。

当用户点击一个帐户时,我想做一些与这 4 个步骤有点不同的事情。我想做一些类似静默登录的事情,因为我们已经知道应该登录哪个帐户。我不希望 Google 登录帐户选择对话框出现在我必须再次选择该地址的地方。最坏的情况是,用户最初点击 Account-1@gmail.com 并打算登录 Account-1@gmail.com,但在选择器中他随后 selects Account-2@gmail.com,这会有点棘手和烦人。

其中一个 "solution" 不是提供已知帐户列表,而是提供一个 "Sign-In with Google" 按钮,让 Google Play 服务显示选择器对话框。但这会导致两个问题: 1) 像 Gmail 或 Inbox 那样显示应用程序已知的帐户列表不再有意义,因为对任何帐户的任何点击都会再次询问。 2) 当我断开与互联网的连接并启动登录时,SignInIntent 将失败,使应用程序处于奇怪的半登录状态,其中显示来自 Account1 的数据但 Account1 实际上未登录(或Account2 显示但实际上未登录),并且在重新连接到 Internet 时,必须再次显示帐户选择器对话框,然后用户必须 select 他已经在使用的帐户。这太糟糕了。

目前我的解决方案是不允许用户进入登录状态,除非 Google 登录 + Firebase 设法正确登录,这意味着我不会加载数据该用户的本地数据库,并且该用户在再次访问互联网之前无法使用他的数据。这很糟糕。

我想允许用户切换账号,如果Google登录失败,那么让Android/Google登录记住账号,我给用户看他的数据对于该帐户,一旦互联网连接再次出现,我想让用户静默登录到 Firebase 和我的后端,而不显示帐户选择器对话框。

问题一:这个可以用Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient)实现吗?如果是这样,如何?因为我总是得到一个 GoogleSignInStatusCodes.SIGN_IN_REQUIRED,这迫使我从上面开始执行传统的 4 个步骤并显示帐户选择器对话框。顺便说一句,在我成功登录 Google 之后,我在登录 Firebase 帐户后退出了那个 Google 帐户,因为我不再需要那个 Google 帐户了。此外,在任何登录尝试之前,我会调用 Auth.GoogleSignInApi.signOut(mGoogleApiClient); 如果这是 GoogleSignInStatusCodes.SIGN_IN_REQUIRED 的原因,我如何才能保留这样的帐户信息,或者图书馆会处理这些信息?

此外,我没有看到将电子邮件地址传递给 Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient) 的方法,因此我无法使用该方法从一个帐户切换到另一个帐户,因为我必须退出一个帐户,然后再请求登录第二个帐户。这让我相信我不能使用这种方法来提供已知帐户的列表,例如在导航抽屉中,因为切换将需要该对话框再次显示,这会扰乱工作流程。

那么,问题2: 已经登录过一次的账号,如何只用邮箱或者user_id静默登录?

作为额外的,我想从帐户选择器对话框中过滤掉已经登录过一次的帐户,因为这些帐户将通过中提到的方法登录第二个问题(通过电子邮件或 user_id 到 silentSignIn)

感谢您花时间阅读本文。

有可能。

解决问题的关键是当 "silent" sign-in(没有帐户选择器对话框)应该通过 gsob.setAccountName(...); 将电子邮件地址传递给 GoogleSignInOptions 生成器发生。

GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN);
gsob.requestIdToken(ApplicationCore.getMainActivity().getString(R.string.default_web_client_id));
gsob.requestEmail();
if (strEmail != null && !strEmail.equals("")) {
    gsob.setAccountName(strEmail); // <------------------- here...
}

mGoogleApiClient = new GoogleApiClient.Builder(ApplicationCore.getMainActivity())
        .enableAutoManage(ApplicationCore.getMainActivity(), new GoogleApiClient.OnConnectionFailedListener() {
            @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
                // Do some cleanup here
            }
        })
        .addApi(Auth.GOOGLE_SIGN_IN_API, gsob.build())
        .build();
};

mGoogleApiClient.connect();

这会导致下面的流程,这就是我想要的。