检索用户存储的凭据

使用 Credentials API 请求和检索为用户存储的凭据,以便自动让用户登录您的应用。

准备工作

配置 Android Studio 项目

创建 CredentialsClient 对象

如需请求存储的凭据,您必须创建 CredentialsClient 实例来访问 Credentials API:

CredentialsClient mCredentialsClient;

// ...

mCredentialsApiClient = Credentials.getClient(this);

创建 CredentialRequest 对象

CredentialRequest 对象指定您要从中请求凭据的登录系统。构建 CredentialRequest。对于基于密码的登录,使用 setPasswordLoginSupported 方法;对于联合登录服务(如 Google 登录),使用 setAccountTypes() 方法。

mCredentialRequest = new CredentialRequest.Builder()
    .setPasswordLoginSupported(true)
    .setAccountTypes(IdentityProviders.GOOGLE, IdentityProviders.TWITTER)
    .build();

使用 IdentityProviders 中定义的常量来指定常用的登录提供方。对于其他登录提供方,使用可唯一标识提供方的任何字符串。您必须使用与检索凭据相同的提供方标识符来存储凭据。

请求存储的凭据

创建 CredentialsClientCredentialRequest 对象后,请将请求对象传递给 CredentialsClient.request() 方法,以请求为应用存储的凭据。

  mCredentialsClient.request(mCredentialRequest).addOnCompleteListener(
      new OnCompleteListener<CredentialRequestResponse>() {
          @Override
          public void onComplete(@NonNull Task<CredentialRequestResponse> task) {

              if (task.isSuccessful()) {
                  // See "Handle successful credential requests"
                  onCredentialRetrieved(task.getResult().getCredential());
                  return;
              }

              // See "Handle unsuccessful and incomplete credential requests"
              // ...
          }
      });

定义一个回调,以使用 addOnCompleteListener() 方法处理成功和失败的请求。

处理成功的凭据请求

表明登录成功的消息框 凭据请求成功后,使用生成的 Credential 对象完成用户登录应用。使用 getAccountType() 方法确定检索到的凭据的类型,然后完成相应的登录过程。例如,对于 Google 登录,请创建一个包含用户 ID 的 GoogleSignInClient 对象,然后使用该对象启动登录流程。对于基于密码的登录,请使用 Credential 对象中的用户 ID 和密码来完成应用的登录流程。

private void onCredentialRetrieved(Credential credential) {
    String accountType = credential.getAccountType();
    if (accountType == null) {
        // Sign the user in with information from the Credential.
        signInWithPassword(credential.getId(), credential.getPassword());
    } else if (accountType.equals(IdentityProviders.GOOGLE)) {
        // The user has previously signed in with Google Sign-In. Silently
        // sign in the user with the same ID.
        // See https://developers.google.com/identity/sign-in/android/
        GoogleSignInOptions gso =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestEmail()
                        .build();

        GoogleSignInClient signInClient = GoogleSignIn.getClient(this, gso);
        Task<GoogleSignInAccount> task = signInClient.silentSignIn();
        // ...
    }
}

处理多个已保存的凭据

Smart Lock 帐号选择器

当需要用户输入选择凭据时,request() 任务将失败并显示 ResolvableApiException。检查 getStatusCode() 是否返回 RESOLUTION_REQUIRED,并调用异常的 startResolutionForResult() 方法来提示用户选择帐号。然后,通过将 Credential.EXTRA_KEY 传递给 getParcelableExtra() 方法,从 activity 的 onActivityResult() 方法中检索用户选择的凭据。

mCredentialsClient.request(request).addOnCompleteListener(
        new OnCompleteListener() {
            @Override
            public void onComplete(@NonNull Task task) {
                if (task.isSuccessful()) {
                    // ...
                    return;
                }

                Exception e = task.getException();
                if (e instanceof ResolvableApiException) {
                    // This is most likely the case where the user has multiple saved
                    // credentials and needs to pick one. This requires showing UI to
                    // resolve the read request.
                    ResolvableApiException rae = (ResolvableApiException) e;
                    resolveResult(rae, RC_READ);
                } else if (e instanceof ApiException) {
                    // The user must create an account or sign in manually.
                    Log.e(TAG, "Unsuccessful credential request.", e);

                    ApiException ae = (ApiException) e;
                    int code = ae.getStatusCode();
                    // ...
                }
            }
        });
private void resolveResult(ResolvableApiException rae, int requestCode) {
    try {
        rae.startResolutionForResult(MainActivity.this, requestCode);
        mIsResolving = true;
    } catch (IntentSender.SendIntentException e) {
        Log.e(TAG, "Failed to send resolution.", e);
        hideProgress();
    }
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // ...

    if (requestCode == RC_READ) {
        if (resultCode == RESULT_OK) {
            Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
            onCredentialRetrieved(credential);
        } else {
            Log.e(TAG, "Credential Read: NOT OK");
            Toast.makeText(this, "Credential Read Failed", Toast.LENGTH_SHORT).show();
        }
    }

    // ...

}

如果未找到存储的凭据,用户必须创建帐号或手动登录。如果 getStatusCode() 返回 SIGN_IN_REQUIRED,您可以选择提示用户选择最近用过的登录信息(例如电子邮件地址和姓名),并使用该信息自动填充表单的某些字段,从而加快注册和登录流程。如需了解详情,请参阅向用户提供登录提示

成功登录后,允许用户保存其凭据,以便将来在其所有设备上自动进行身份验证。