擷取使用者(') 已儲存的憑證

使用 Credentials API 為使用者要求及擷取已儲存的憑證,以便自動讓使用者登入應用程式。

事前準備

設定 Android Studio 專案

建立 CredentialsClient 物件

如想要求已儲存的憑證,您必須建立 CredentialsClient 執行個體來存取 Credentials API:

CredentialsClient mCredentialsClient;

// ...

mCredentialsApiClient = Credentials.getClient(this);

建立 CredentialRequest 物件

CredentialRequest 物件會指定您想從哪個登入系統要求憑證。使用 setPasswordLoginSupported 方法進行密碼登入作業,以及為聯合登入服務 (例如 Google 登入) 使用 setAccountTypes() 方法建構 CredentialRequest

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

使用 IdentityProviders 中定義的常數,指定常用的登入提供者。至於其他登入提供者,請使用任何可明確識別該提供者的字串。您必須使用同一個提供者 ID 來儲存用於擷取憑證的憑證。

要求已儲存的憑證

建立 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 物件,然後使用該物件啟動登入流程。對於密碼式登入,請使用憑證物件中的使用者 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() 方法,以便從活動的 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,您可以選擇提示使用者選擇最近使用的登入資訊 (例如電子郵件地址和姓名),並在表單的某些欄位中自動填入該資訊,藉此加快註冊和登入程序。詳情請參閱「為使用者提供登入提示」。

使用者成功登入後,可儲存自己的憑證,以便日後在所有裝置上自動進行驗證。