Android GoogleSignIn:同时多个帐户+失败时推迟登录 [英] Android GoogleSignIn: Multiple accounts at the same time + deferred sign-in upon failure

查看:142
本文介绍了Android GoogleSignIn:同时多个帐户+失败时推迟登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我正在提供Google登录和基于电子邮件/密码的身份验证.电子邮件/密码很简单.

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

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

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

3)在onActivityResult中,我得到 result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);,然后从那里GoogleSignInAccount account = .getSignInAccount(),最后我通过调用mFirebaseAuth.signInWithCredential(GoogleAuthProvider.getCredential( account .getIdToken(), null))

登录到Firebase

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

这四个步骤有效.我可以将应用程序登录到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登录+ Firebase设法正确登录,否则不允许用户进入登录状态,这意味着我不会为该用户从本地数据库加载数据并且用户只有在再次访问互联网后才能使用自己的数据.这很糟糕.

我希望允许用户切换帐户,如果Google登录失败,则让Android/Google登录帐户记住该帐户,然后我会尽快向该用户显示该帐户的数据再次有Internet连接,我想在不显示帐户选择器"对话框的情况下以静默方式登录用户到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来以静默方式登录已经登录过的帐户?

另外,我想从帐户选择器"对话框中筛选出已经登录过一次的帐户,因为随后这些帐户将通过第二个问题(通过电子邮件或user_id发送给silentSignIn)

感谢您抽出宝贵的时间阅读这篇文章.

解决方案

可能.

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

这将导致以下流程,这正是我想要的.

I'm coding an app which makes use of Firebase Authentication to authenticate with my backend server.

I'm offering Google Sign-In and Email/Password based authentication. Email/Password is trivial.

This is my flow for using Google Sign-In:

1) I create a mGoogleApiClient= new GoogleApiClient with .addApi(Auth.GOOGLE_SIGN_IN_API, gso), where gso= GoogleSignInOptions with .requestIdToken(...)) and .requestEmail()

2) I call startActivityForResult(signInIntent, RC_GOOGLE_SIGN_IN); where signInIntent= Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)

3) In the onActivityResult I get the result= Auth.GoogleSignInApi.getSignInResultFromIntent(data); and from there GoogleSignInAccountaccount=result.getSignInAccount() with which I finally log into Firebase by calling mFirebaseAuth.signInWithCredential(GoogleAuthProvider.getCredential(account.getIdToken(), null))

4) Then I "generate"/retrieve a Firebase JWT via fbUser.getToken(false) which I then send to the backend server to create/authenticate the user over there.

The 4 steps work. I am able to sign the app into Firebase and into my backend server.

This is fine if I want to use only one account at a time. Actually, that is what I want to do, but my problem is the following:

I want to, just like Gmail or Inbox does, offer a list of accounts which have been signed in at least once via the 4 steps mentioned above.

When the user clicks on an account, then I want do so something which is a bit different than those 4 steps. I want to do something like a silent sign in, since we already know which account should get signed into. I don't want the Google Sign-In Account Selection Dialog to appear where I have to choose that address again. Worst case scenario the User initially taps the Account-1@gmail.com with the intention to sign into Account-1@gmail.com, but in the Chooser he then selects Account-2@gmail.com, which would be a bit tricky and annoying.

One "solution" to this is not to offer a list of known accounts, but just a "Sign-In with Google"-Button, which lets the Google Play Services present the chooser dialog. But this causes two problems: 1) It no longer makes sense to show a list of accounts which are known to the app like Gmail or Inbox does, because any click on any account will ask for a second time. 2) When I'm disconnected from the internet and initiate a Sign-In, the SignInIntent will fail, leaving the app in an odd semi-signed in state, where the data from Account1 is shown but Account1 is actually not signed in (or Account2 is shown but is actually not signed in), and upon a reconnect to the internet that Account Chooser Dialog must be shown again, where the user must then select the account which he is already using. This is awful.

Currently my solution is to not allow the user to get into a signed-in state unless Google Sign-In + Firebase manages to sign in correctly, which means that I won't load the data from the local database for that user and the user can't use his data until he gets internet access again. This is very bad.

I would like to allow the user to switch the account, and if Google Sign-In fails, then have Android/Google Sign-In remember the account, and I show the user his data for that account, and as soon as internet connectivity is there again I would like to sign-in the user silently into Firebase and my backend, without showing an Account Chooser Dialog.

Question 1: Can this archieved with Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient)? If so, how? Because I'm always getting a GoogleSignInStatusCodes.SIGN_IN_REQUIRED which forces me to go through the traditional 4 steps from above and show the Account Chooser Dialog. On a note aside, after I sign into Google successfully, I sign out of that Google account after signing into the Firebase account, since I don't need that Google account anymore. Also, before any sign-in attempt I call Auth.GoogleSignInApi.signOut(mGoogleApiClient); If that is the reason for the GoogleSignInStatusCodes.SIGN_IN_REQUIRED, how can I persist such an account info, or will the library take care of that?

Also, I don't see a way to pass an Email address to Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient), so I can't use that method to switch from one account to another, since I would have to sign out the one account before requesting the sign-in of the second one. This leads me to believe that I can't use this method to offer a list of already-known accounts, for example in a Navigation Drawer, since switch will require that Dialog to show up again, which messes with the workflow.

So, Question 2: How can I sign-in an account which already got signed in once in a silent manner only by using the email or the user_id?

As an extra, I would like to filter out from the Account Chooser Dialog the accounts which already signed in once, because those then would get signed into via the method mentioned in the second question (pass an email or user_id to the silentSignIn)

Thanks for taking the time to read this.

解决方案

It is possible.

The key to solving the problem is to pass the email address to the GoogleSignInOptions builder via gsob.setAccountName(...); when a "silent" sign-in (no account chooser dialog) should occur.

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

This then leads to the following flow, which is what I wanted.

这篇关于Android GoogleSignIn:同时多个帐户+失败时推迟登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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