Android 使用旧密码登录Google帐户-如何重定向到蓝色Google登录页面?

Android 使用旧密码登录Google帐户-如何重定向到蓝色Google登录页面?,android,google-signin,google-account,google-identity,Android,Google Signin,Google Account,Google Identity,我已经在我的应用程序中实现了Google登录SDK,它运行良好。 单击“登录”按钮时,会打开一个窗口,显示已存储的帐户。选择其中一个帐户将成功结束登录过程 一个未通过的用例是当用户进入登录对话框并单击密码无效的帐户时。我不知道如何解决这个问题 我按照谷歌指令“实现登录SDK”,并在调用这些行之后: Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); GoogleSignI

我已经在我的应用程序中实现了Google登录SDK,它运行良好。 单击“登录”按钮时,会打开一个窗口,显示已存储的帐户。选择其中一个帐户将成功结束登录过程

一个未通过的用例是当用户进入登录对话框并单击密码无效的帐户时。我不知道如何解决这个问题


我按照谷歌指令“实现登录SDK”,并在调用这些行之后:

Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);
在活动结果的
部分:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");

    if (requestCode == RequestCodes.RC_GOOGLE_SIGN_IN) {

        try {

            // Call to take account data
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);

            // Fetch account data
            GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);

            Account account = googleSignInAccount.getAccount();

            // Calling to get short lived token
            String shortLivedToken = GoogleAuthUtil.getToken(mContext, account, "oauth2:" + Scopes.PROFILE + " " + Scopes.EMAIL);

            // Further calls here...

        } catch (ApiException e) {

            //https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes

            if (e.getStatusCode() == 12501) {
                Log.e(TAG, "SIGN_IN_CANCELLED");
            } else if (e.getStatusCode() == 12502) {
                Log.e(TAG, "SIGN_IN_CURRENTLY_IN_PROGRESS");
            } else if (e.getStatusCode() == 12500) {
                Log.e(TAG, "SIGN_IN_FAILED");
            } else {
                e.printStackTrace();
            }

        } catch (GoogleAuthException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}
@覆盖
受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
Log.d(标记,“onActivityResult()调用时使用:requestCode=[“+requestCode+”],resultCode=[“+resultCode+”],data=[“+data+”]);
if(requestCode==RequestCodes.RC\u谷歌\u登录){
试一试{
//调用以考虑数据
Task Task=GoogleSignIn.GetSignedAccountFromIntent(数据);
//获取帐户数据
GoogleSignInAccount GoogleSignInAccount=task.getResult(ApiException.class);
Account=googleSignInAccount.getAccount();
//呼叫以获取短期令牌
String shortLivedToken=GoogleAuthUtil.getToken(mContext,account,“oauth2:”+Scopes.PROFILE+“”+Scopes.EMAIL);
//这里还有更多的电话。。。
}捕获(APIE){
//https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes
如果(如getStatusCode()==12501){
Log.e(标签“签到取消”);
}否则如果(例如getStatusCode()==12502){
Log.e(标记“正在进行中的签名”);
}否则如果(例如getStatusCode()==12500){
Log.e(标记“登录失败”);
}否则{
e、 printStackTrace();
}
}捕获(googleauthe异常){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
}否则{
super.onActivityResult(请求代码、结果代码、数据);
}
}

免责声明 我不是谷歌的员工。下面我所说的一切都是我从调查类似问题中得出的结论

简短回答

你做的一切都对。这是登录google帐户的推荐方式。 不幸的是,在这个机制中没有实际的回调来指定在您的案例中实际发生了什么错误。Google Play Services处理此问题的方式是通过如下所示的通知通知用户其凭据已过时(密码更改后)

我建议您在上为您的案例添加额外的结果代码,因为这似乎是一个合理的改进

长答案

谷歌和其他人一样使用它(你可以自己试试)。 在幕后,它只是一个oauth令牌检索和存储机制

更改密码时,令牌不再有效,您在尝试使用时会出错

它的工作方式是Google Play服务开发人员选择的实现方式(因此我建议您提交一个bug)

例如,AliExpress可以以某种方式处理此问题,并将用户重定向到 蓝色页面,要求用户再次登录

Aliexpress使用。正如你所看到的,选择账户的对话框有不同的颜色,没有头像。API仍然可用,但可能随时关闭(或不关闭)。我不建议您使用此功能,但其工作原理如下:

import com.google.android.gms.common.AccountPicker;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;

void chooseAccount() {
    Intent signInIntent = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
    startActivityForResult(signInIntent, REQ_CHOOSE_ACCOUNT);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == REQ_CHOOSE_ACCOUNT) {

        String email = data.getExtras().getString("authAccount");
        // better do this in background thread
        try {
            GoogleAuthUtil.getToken(this, new Account(email, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE), "oauth2:https://www.googleapis.com/auth/userinfo.profile");
        } catch (UserRecoverableAuthException recEx) {
            Intent recoverIntent = recEx.getIntent();
            // Will redirect to login activity
            startActivityForResult(recoverIntent, REQ_RECOVER);
        } catch (Exception e) {
            Log.d(TAG, "caught exception", e);
        }

    }
}
希望有帮助

UPD:新的Google Play API扩展了您正在捕获的API异常。它的方法startResolutionForResult()与旧API中使用的方法类似。但您收到的捆绑包不包含解决方案信息

Bundle[{googleSignInStatus=Status{statusCode=unknown status code: 12501, resolution=null}}]
如果您要提交bug,请将其发布在此处,我们将启动它)

您还可以使用默认的Android API(min API 23)显示“选择帐户”对话框。

可能会使用以下代码显示“选择帐户对话框”。这是新的,而且(希望)在一段时间内不会被弃用

import android.accounts.Account;
import android.accounts.AccountManager;

// Unfortunately can be used only on API 23 and higher
Intent signInIntent = AccountManager.newChooseAccountIntent(
            null,
            null,
            new String[] { "com.google" },
            "Please select your account",
            null,
            null,
            new Bundle());

startActivityForResult(signInIntent, REQ_SELECT_ACCOUNT);

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQ_SELECT_ACCOUNT) {
            String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
            String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
            // now you can call GoogleAuthUtil as in example above
        }
    }
您还可以获取应用程序可见的谷歌账户列表

在用户尝试使用上述方法之一使用该类型的帐户登录到您的应用程序后,您的应用程序将可以看到该帐户。事件如果登录不成功(例如密码过期),您将在列表中看到此帐户(但在多个帐户的情况下无法区分哪个帐户)。因此,这可以作为解决办法,但方式有限

import android.accounts.Account;
import android.accounts.AccountManager;

try {
        // requires android.permission.GET_ACCOUNTS
        Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
        for (Account account : accounts) {
            Log.d(TAG, "account: " + account.name);
        }
    } catch (Exception e) {
        Log.i("Exception", "Exception:" + e);
    }
结论
不幸的是,我还没有找到其他方法来访问谷歌帐户数据,以解决您使用现代谷歌登录API的情况。所有高级AccountManager API都要求您拥有与帐户所有者应用程序(GMS-谷歌移动服务)相同的签名,但事实并非如此。因此,我们只能向谷歌提出请求,并希望能够实施:(

我不知道native,但在js api中,您可以先调用注销,然后用户必须选择一个帐户,并在下次登录时输入他的凭据。也许这就是方向。我恐怕这不是我的情况。注销不会重置或删除帐户列表对话框中的用户。我认为您无法执行任何操作about除了通知用户他必须重新登录到他的google帐户或类似的东西之外that@AntonisRadz嗯,我知道这是可能的,因为它已经被证明。只留下一条消息是一个糟糕的用户体验。@死鱼如果像这里这样简单地撤销帐户,然后再次要求登录?或者在撤销后尝试正常登录他是档案虫等待星星-@deadfish我已经主演了它。希望它能得到足够多的星星来认真对待
import android.accounts.Account;
import android.accounts.AccountManager;

try {
        // requires android.permission.GET_ACCOUNTS
        Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
        for (Account account : accounts) {
            Log.d(TAG, "account: " + account.name);
        }
    } catch (Exception e) {
        Log.i("Exception", "Exception:" + e);
    }