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

Posted

技术标签:

【中文标题】Android GoogleSignIn:多个帐户同时+失败时延迟登录【英文标题】:Android GoogleSignIn: Multiple accounts at the same time + deferred sign-in upon failure 【发布时间】:2017-06-02 02:29:01 【问题描述】:

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

我提供基于 Google 登录和电子邮件/密码的身份验证。电子邮件/密码是微不足道的。

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

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

2) 我打电话给startActivityForResult(signInIntent, RC_GOOGLE_SIGN_IN); 其中signInIntent= Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)

3) 在onActivityResult 我得到result= Auth.GoogleSignInApi.getSignInResultFromIntent(data); 并从那里得到GoogleSignInAccountaccount=@987654341 @.getSignInAccount() 我最终通过调用 mFirebaseAuth.signInWithCredential(GoogleAuthProvider.getCredential(account.getIdToken(), null))

登录 Firebase

4) 然后我通过fbUser.getToken(false)“生成”/检索 Firebase JWT,然后将其发送到后端服务器以创建/验证那里的用户。

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

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

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

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

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

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

我想允许用户切换帐户,如果 Google 登录失败,则让 android/Google 登录记住该帐户,我会向用户显示该帐户的数据,并尽快互联网连接再次出现我想以静默方式将用户登录到 Firebase 和我的后端,而不显示帐户选择器对话框。

问题 1: 可以用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 以静默方式登录已经登录过一次的帐户?

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

感谢您花时间阅读本文。

【问题讨论】:

【参考方案1】:

有可能。

解决问题的关键是在应该出现“静默”登录(无帐户选择器对话框)时通过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();

这将导致以下流程,这就是我想要的。

【讨论】:

以上是关于Android GoogleSignIn:多个帐户同时+失败时延迟登录的主要内容,如果未能解决你的问题,请参考以下文章

Android:GoogleAuthUtil.getToken - 帐户对象应该来自哪里?

无法解析 GoogleSignIn 和 GoogleSignInClient

谷歌使用 GIDSignin 多次登录

GoogleSignIn 重复登录弹出窗口并且不会转到 Android API 30 的 onActivityResult

将 Android GoogleSignIn 与 GmailScopes.GMAIL_SEND 一起使用(gmail api)

Flutter+Firebase 将匿名用户升级到 GoogleSignIn 时出错(给定字符串为空或 null)