Hiển thị hộp thoại xác thực sinh trắc học

Một phương thức bảo vệ thông tin nhạy cảm hoặc nội dung hàng đầu trong ứng dụng của bạn là yêu cầu xác thực bằng sinh trắc học, chẳng hạn như sử dụng tính năng nhận dạng khuôn mặt hoặc nhận dạng vân tay. Hướng dẫn này giải thích cách hỗ trợ luồng đăng nhập bằng sinh trắc học trong ứng dụng của bạn.

Khai báo loại xác thực được ứng dụng của bạn hỗ trợ

Để xác định các loại xác thực được ứng dụng của bạn hỗ trợ, hãy dùng giao diện BiometricManager.Authenticators. Bạn có thể khai báo các loại xác thực sau:

BIOMETRIC_STRONG
Xác thực bằng thông tin sinh trắc học Lớp 3, như xác định trên trang định nghĩa về khả năng tương thích với Android..
BIOMETRIC_WEAK
Xác thực bằng thông tin sinh trắc học Lớp 2, như xác định trên trang định nghĩa về khả năng tương thích với Android..
DEVICE_CREDENTIAL
Xác thực bằng thông tin xác thực khoá màn hình – mã PIN, hình mở khoá hoặc mật khẩu của người dùng.

Để bắt đầu sử dụng trình xác thực, người dùng cần tạo mã PIN, hình mở khoá hoặc mật khẩu. Nếu người dùng chưa có mã xác thực, thì quy trình đăng ký nhận dạng sinh trắc học sẽ nhắc họ tạo mã.

Để xác định các kiểu xác thực bằng sinh trắc học, được ứng dụng của bạn chấp nhận, hãy chuyển một kiểu xác thực hoặc một tổ hợp bitwise nhiều kiểu xác thực vào phương thức setAllowedAuthenticators(). Đoạn mã sau đây cho thấy cách hỗ trợ xác thực bằng thông tin sinh trắc học Lớp 3 hoặc thông tin xác thực khoá màn hình.

Kotlin

// Lets the user authenticate using either a Class 3 biometric or
// their lock screen credential (PIN, pattern, or password).
promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
        .build()

Java

// Lets user authenticate using either a Class 3 biometric or
// their lock screen credential (PIN, pattern, or password).
promptInfo = new BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)
        .build();

Trên Android 10 (API cấp 29) trở xuống, bạn không thể kết hợp các loại trình xác thực sau: DEVICE_CREDENTIALBIOMETRIC_STRONG | DEVICE_CREDENTIAL. Để kiểm tra sự hiện diện của mã PIN, hình mở khoá hoặc mật khẩu trên Android 10 trở xuống, hãy sử dụng phương thức KeyguardManager.isDeviceSecure().

Kiểm tra xem phương thức xác thực bằng sinh trắc học có trên thiết bị không

Sau khi bạn quyết định chọn phần tử xác thực nào được ứng dụng của bạn hỗ trợ, hãy kiểm tra xem các phần tử này có trên thiết bị không. Để thực hiện việc này, hãy chuyển cùng một kiểu kết hợp bitwise mà bạn đã khai báo bằng phương thức setAllowedAuthenticators() vào phương thức canAuthenticate(). Nếu cần, hãy gọi thao tác theo ý định ACTION_BIOMETRIC_ENROLL. Trong phần ý định bổ sung, cung cấp tập hợp trình xác thực được ứng dụng của bạn chấp nhận. Ý định này nhắc người dùng đăng ký thông tin xác thực với trình xác thực mà ứng dụng của bạn chấp nhận.

Kotlin

val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) {
    BiometricManager.BIOMETRIC_SUCCESS ->
        Log.d("MY_APP_TAG", "App can authenticate using biometrics.")
    BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
        Log.e("MY_APP_TAG", "No biometric features available on this device.")
    BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
        Log.e("MY_APP_TAG", "Biometric features are currently unavailable.")
    BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
        // Prompts the user to create credentials that your app accepts.
        val enrollIntent = Intent(Settings.ACTION_BIOMETRIC_ENROLL).apply {
            putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
        }
        startActivityForResult(enrollIntent, REQUEST_CODE)
    }
}

Java

BiometricManager biometricManager = BiometricManager.from(this);
switch (biometricManager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
    case BiometricManager.BIOMETRIC_SUCCESS:
        Log.d("MY_APP_TAG", "App can authenticate using biometrics.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
        Log.e("MY_APP_TAG", "No biometric features available on this device.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
        Log.e("MY_APP_TAG", "Biometric features are currently unavailable.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
        // Prompts the user to create credentials that your app accepts.
        final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
        enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
        startActivityForResult(enrollIntent, REQUEST_CODE);
        break;
}

Xác định cách người dùng được xác thực

Sau khi người dùng xác thực, bạn có thể kiểm tra xem người dùng được xác thực bằng thông tin đăng nhập thiết bị hay thông tin xác thực sinh trắc học bằng cách gọi getAuthenticationType().

Hiển thị lời nhắc đăng nhập

Để hiển thị lời nhắc của hệ thống đòi hỏi người dùng xác thực bằng thông tin xác thực sinh trắc học, sử dụng Thư viện sinh trắc học. Hộp thoại này (do hệ thống cung cấp) là nhất quán trên các ứng dụng dùng hộp thoại này, tạo ra trải nghiệm người dùng đáng tin cậy hơn. Hộp thoại mẫu được minh hoạ trong hình 1.

Ảnh chụp màn hình minh hoạ hộp thoại
Hình 1. Hộp thoại của hệ thống yêu cầu xác thực sinh trắc học.

Để thêm tính năng xác thực bằng sinh trắc học vào ứng dụng của bạn bằng thư viện Sinh trắc học, hãy hoàn tất các bước sau:

  1. Trong tệp build.gradle của mô-đun ứng dụng, thêm phần phụ thuộc vào thư viện androidx.biometric.

  2. Trong hoạt động hoặc mảnh lưu trữ hộp thoại đăng nhập sinh trắc học, hiển thị hộp thoại sử dụng logic có trong đoạn mã sau:

    Kotlin

    private lateinit var executor: Executor
    private lateinit var biometricPrompt: BiometricPrompt
    private lateinit var promptInfo: BiometricPrompt.PromptInfo
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        executor = ContextCompat.getMainExecutor(this)
        biometricPrompt = BiometricPrompt(this, executor,
                object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationError(errorCode: Int,
                    errString: CharSequence) {
                super.onAuthenticationError(errorCode, errString)
                Toast.makeText(applicationContext,
                    "Authentication error: $errString", Toast.LENGTH_SHORT)
                    .show()
            }
    
            override fun onAuthenticationSucceeded(
                    result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                Toast.makeText(applicationContext,
                    "Authentication succeeded!", Toast.LENGTH_SHORT)
                    .show()
            }
    
            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                Toast.makeText(applicationContext, "Authentication failed",
                    Toast.LENGTH_SHORT)
                    .show()
            }
        })
    
        promptInfo = BiometricPrompt.PromptInfo.Builder()
                .setTitle("Biometric login for my app")
                .setSubtitle("Log in using your biometric credential")
                .setNegativeButtonText("Use account password")
                .build()
    
        // Prompt appears when user clicks "Log in".
        // Consider integrating with the keystore to unlock cryptographic operations,
        // if needed by your app.
        val biometricLoginButton =
                findViewById<Button>(R.id.biometric_login)
        biometricLoginButton.setOnClickListener {
            biometricPrompt.authenticate(promptInfo)
        }
    }
    

    Java

    private Executor executor;
    private BiometricPrompt biometricPrompt;
    private BiometricPrompt.PromptInfo promptInfo;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        executor = ContextCompat.getMainExecutor(this);
        biometricPrompt = new BiometricPrompt(MainActivity.this,
                executor, new BiometricPrompt.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode,
                    @NonNull CharSequence errString) {
                super.onAuthenticationError(errorCode, errString);
                Toast.makeText(getApplicationContext(),
                    "Authentication error: " + errString, Toast.LENGTH_SHORT)
                    .show();
            }
    
            @Override
            public void onAuthenticationSucceeded(
                    @NonNull BiometricPrompt.AuthenticationResult result) {
                super.onAuthenticationSucceeded(result);
                Toast.makeText(getApplicationContext(),
                    "Authentication succeeded!", Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onAuthenticationFailed() {
                super.onAuthenticationFailed();
                Toast.makeText(getApplicationContext(), "Authentication failed",
                    Toast.LENGTH_SHORT)
                    .show();
            }
        });
    
        promptInfo = new BiometricPrompt.PromptInfo.Builder()
                .setTitle("Biometric login for my app")
                .setSubtitle("Log in using your biometric credential")
                .setNegativeButtonText("Use account password")
                .build();
    
        // Prompt appears when user clicks "Log in".
        // Consider integrating with the keystore to unlock cryptographic operations,
        // if needed by your app.
        Button biometricLoginButton = findViewById(R.id.biometric_login);
        biometricLoginButton.setOnClickListener(view -> {
                biometricPrompt.authenticate(promptInfo);
        });
    }
    

Sử dụng giải pháp mật mã phụ thuộc vào xác thực

Để tăng cường bảo vệ thông tin nhạy cảm trong ứng dụng của mình, bạn có thể tích hợp tính năng mật mã vào quy trình xác thực bằng sinh trắc học bằng cách sử dụng một thực thể của CryptoObject. Khung này hỗ trợ các đối tượng mật mã sau: Signature, CipherMac.

Sau khi người dùng xác thực thành công bằng lời nhắc sinh trắc học, ứng dụng của bạn có thể thực hiện thao tác mã hoá. Ví dụ: nếu xác thực bằng đối tượng Cipher, thì ứng dụng của bạn có thể thực hiện việc mã hoá và giải mã bằng đối tượng SecretKey.

Trong các phần sau, bạn sẽ tìm hiểu các ví dụ về sử dụng đối tượng Cipher và đối tượng SecretKey để mã hoá dữ liệu. Mỗi ví dụ sử dụng các phương thức sau:

Kotlin

private fun generateSecretKey(keyGenParameterSpec: KeyGenParameterSpec) {
    val keyGenerator = KeyGenerator.getInstance(
            KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
    keyGenerator.init(keyGenParameterSpec)
    keyGenerator.generateKey()
}

private fun getSecretKey(): SecretKey {
    val keyStore = KeyStore.getInstance("AndroidKeyStore")

    // Before the keystore can be accessed, it must be loaded.
    keyStore.load(null)
    return keyStore.getKey(KEY_NAME, null) as SecretKey
}

private fun getCipher(): Cipher {
    return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
            + KeyProperties.BLOCK_MODE_CBC + "/"
            + KeyProperties.ENCRYPTION_PADDING_PKCS7)
}

Java

private void generateSecretKey(KeyGenParameterSpec keyGenParameterSpec) {
    KeyGenerator keyGenerator = KeyGenerator.getInstance(
            KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
    keyGenerator.init(keyGenParameterSpec);
    keyGenerator.generateKey();
}

private SecretKey getSecretKey() {
    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");

    // Before the keystore can be accessed, it must be loaded.
    keyStore.load(null);
    return ((SecretKey)keyStore.getKey(KEY_NAME, null));
}

private Cipher getCipher() {
    return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
            + KeyProperties.BLOCK_MODE_CBC + "/"
            + KeyProperties.ENCRYPTION_PADDING_PKCS7);
}

Xác thực chỉ bằng thông tin xác thực sinh trắc học

Nếu ứng dụng của bạn sử dụng khoá bí mật đòi hỏi thông tin xác thực sinh trắc học để mở khoá, thì người dùng phải xác thực thông tin xác thực sinh trắc học của họ mỗi lần ứng dụng truy cập vào khoá.

Để chỉ mã hoá thông tin nhạy cảm sau khi người dùng xác thực bằng thông tin xác nhận sinh trắc học, hãy hoàn tất các bước sau:

  1. Tạo khoá sử dụng cấu hình sau đây KeyGenParameterSpec:

    Kotlin

    generateSecretKey(KeyGenParameterSpec.Builder(
            KEY_NAME,
            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
            .setUserAuthenticationRequired(true)
            // Invalidate the keys if the user has registered a new biometric
            // credential, such as a new fingerprint. Can call this method only
            // on Android 7.0 (API level 24) or higher. The variable
            // "invalidatedByBiometricEnrollment" is true by default.
            .setInvalidatedByBiometricEnrollment(true)
            .build())
    

    Java

    generateSecretKey(new KeyGenParameterSpec.Builder(
            KEY_NAME,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
            .setUserAuthenticationRequired(true)
            // Invalidate the keys if the user has registered a new biometric
            // credential, such as a new fingerprint. Can call this method only
            // on Android 7.0 (API level 24) or higher. The variable
            // "invalidatedByBiometricEnrollment" is true by default.
            .setInvalidatedByBiometricEnrollment(true)
            .build());
    
  2. Bắt đầu một quy trình xác thực bằng sinh trắc học kết hợp một thuật toán mật mã:

    Kotlin

    biometricLoginButton.setOnClickListener {
        // Exceptions are unhandled within this snippet.
        val cipher = getCipher()
        val secretKey = getSecretKey()
        cipher.init(Cipher.ENCRYPT_MODE, secretKey)
        biometricPrompt.authenticate(promptInfo,
                BiometricPrompt.CryptoObject(cipher))
    }
    

    Java

    biometricLoginButton.setOnClickListener(view -> {
        // Exceptions are unhandled within this snippet.
        Cipher cipher = getCipher();
        SecretKey secretKey = getSecretKey();
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        biometricPrompt.authenticate(promptInfo,
                new BiometricPrompt.CryptoObject(cipher));
    });
    
  3. Bên trong các lệnh gọi lại xác thực bằng sinh trắc học của bạn, hãy sử dụng khoá bí mật để mã hoá thông tin nhạy cảm:

    Kotlin

    override fun onAuthenticationSucceeded(
            result: BiometricPrompt.AuthenticationResult) {
        val encryptedInfo: ByteArray = result.cryptoObject.cipher?.doFinal(
            // plaintext-string text is whatever data the developer would like
            // to encrypt. It happens to be plain-text in this example, but it
            // can be anything
                plaintext-string.toByteArray(Charset.defaultCharset())
        )
        Log.d("MY_APP_TAG", "Encrypted information: " +
                Arrays.toString(encryptedInfo))
    }
    

    Java

    @Override
    public void onAuthenticationSucceeded(
            @NonNull BiometricPrompt.AuthenticationResult result) {
        // NullPointerException is unhandled; use Objects.requireNonNull().
        byte[] encryptedInfo = result.getCryptoObject().getCipher().doFinal(
            // plaintext-string text is whatever data the developer would like
            // to encrypt. It happens to be plain-text in this example, but it
            // can be anything
                plaintext-string.getBytes(Charset.defaultCharset()));
        Log.d("MY_APP_TAG", "Encrypted information: " +
                Arrays.toString(encryptedInfo));
    }

Xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin đăng nhập màn hình khoá

Bạn có thể sử dụng khoá bí mật cho phép xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin đăng nhập màn hình khoá (mã PIN, hình mở khoá hoặc mật khẩu). Khi định cấu hình cho khoá này, hãy chỉ định khoảng thời gian hợp lệ. Trong khoảng thời gian này, ứng dụng của bạn có thể thực hiện nhiều thao tác mã hoá mà người dùng không cần xác thực lại.

Để mã hoá thông tin nhạy cảm sau khi người dùng xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin xác thực màn hình khoá, hãy hoàn thành các bước sau:

  1. Tạo khoá sử dụng cấu hình sau đây KeyGenParameterSpec:

    Kotlin

    generateSecretKey(KeyGenParameterSpec.Builder(
        KEY_NAME,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
        .setUserAuthenticationRequired(true)
        .setUserAuthenticationParameters(VALIDITY_DURATION_SECONDS,
                ALLOWED_AUTHENTICATORS)
        .build())
    

    Java

    generateSecretKey(new KeyGenParameterSpec.Builder(
        KEY_NAME,
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
        .setUserAuthenticationRequired(true)
        .setUserAuthenticationParameters(VALIDITY_DURATION_SECONDS,
                ALLOWED_AUTHENTICATORS)
        .build());
    
  2. Trong khoảng thời gian VALIDITY_DURATION_SECONDS sau khi người dùng xác thực, mã hoá thông tin nhạy cảm:

    Kotlin

    private fun encryptSecretInformation() {
        // Exceptions are unhandled for getCipher() and getSecretKey().
        val cipher = getCipher()
        val secretKey = getSecretKey()
        try {
            cipher.init(Cipher.ENCRYPT_MODE, secretKey)
            val encryptedInfo: ByteArray = cipher.doFinal(
                // plaintext-string text is whatever data the developer would
                // like to encrypt. It happens to be plain-text in this example,
                // but it can be anything
                    plaintext-string.toByteArray(Charset.defaultCharset()))
            Log.d("MY_APP_TAG", "Encrypted information: " +
                    Arrays.toString(encryptedInfo))
        } catch (e: InvalidKeyException) {
            Log.e("MY_APP_TAG", "Key is invalid.")
        } catch (e: UserNotAuthenticatedException) {
            Log.d("MY_APP_TAG", "The key's validity timed out.")
            biometricPrompt.authenticate(promptInfo)
        }
    

    Java

    private void encryptSecretInformation() {
        // Exceptions are unhandled for getCipher() and getSecretKey().
        Cipher cipher = getCipher();
        SecretKey secretKey = getSecretKey();
        try {
            // NullPointerException is unhandled; use Objects.requireNonNull().
            ciper.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedInfo = cipher.doFinal(
                // plaintext-string text is whatever data the developer would
                // like to encrypt. It happens to be plain-text in this example,
                // but it can be anything
                    plaintext-string.getBytes(Charset.defaultCharset()));
        } catch (InvalidKeyException e) {
            Log.e("MY_APP_TAG", "Key is invalid.");
        } catch (UserNotAuthenticatedException e) {
            Log.d("MY_APP_TAG", "The key's validity timed out.");
            biometricPrompt.authenticate(promptInfo);
        }
    }
    

Xác thực bằng khoá xác thực mỗi lần sử dụng

Bạn có thể hỗ trợ các khoá xác thực cho mỗi lần sử dụng bên trong thực thể của BiometricPrompt. Một khoá như vậy đòi hỏi người dùng nhập thông tin xác thực sinh trắc học hoặc thông tin đăng nhập thiết bị mỗi khi ứng dụng của bạn cần truy cập dữ liệu do khoá đó bảo vệ. Khoá xác thực cho mỗi lần sử dụng có thể hữu ích cho các giao dịch giá trị cao, chẳng hạn như thanh toán một khoản tiền lớn hoặc cập nhật hồ sơ sức khoẻ của một người.

Để liên kết một đối tượng BiometricPrompt với khoá xác thực cho mỗi lần sử dụng, thêm mã tương tự vào mẫu sau:

Kotlin

val authPerOpKeyGenParameterSpec =
        KeyGenParameterSpec.Builder("myKeystoreAlias", key-purpose)
    // Accept either a biometric credential or a device credential.
    // To accept only one type of credential, include only that type as the
    // second argument.
    .setUserAuthenticationParameters(0 /* duration */,
            KeyProperties.AUTH_BIOMETRIC_STRONG or
            KeyProperties.AUTH_DEVICE_CREDENTIAL)
    .build()

Java

KeyGenParameterSpec authPerOpKeyGenParameterSpec =
        new KeyGenParameterSpec.Builder("myKeystoreAlias", key-purpose)
    // Accept either a biometric credential or a device credential.
    // To accept only one type of credential, include only that type as the
    // second argument.
    .setUserAuthenticationParameters(0 /* duration */,
            KeyProperties.AUTH_BIOMETRIC_STRONG |
            KeyProperties.AUTH_DEVICE_CREDENTIAL)
    .build();

Xác thực mà không cần hành động rõ ràng của người dùng

Theo mặc định, hệ thống yêu cầu người dùng thực hiện một hành động cụ thể, chẳng hạn như nhấn một nút, sau khi thông tin xác thực sinh trắc học của người dùng được chấp nhận. Bạn nên ưu tiên dùng cấu hình này nếu ứng dụng của bạn hiển thị hộp thoại để xác nhận một hành động nhạy cảm hoặc có mức độ rủi ro cao, chẳng hạn như mua hàng.

Nếu ứng dụng của bạn hiển thị một hộp thoại xác thực bằng sinh trắc học cho hành động có mức rủi ro thấp hơn, thì bạn có thể gợi ý cho hệ thống rằng người dùng không cần xác nhận xác thực. Gợi ý này có thể cho phép người dùng xem nội dung trong ứng dụng của bạn nhanh hơn sau khi xác thực lại bằng phương thức thụ động, chẳng hạn như nhận dạng khuôn mặt hoặc nhận dạng mống mắt. Để cung cấp gợi ý này, hãy chuyển false vào phương thức setConfirmationRequired().

Hình 2 cho thấy hai phiên bản của cùng một hộp thoại. Một phiên bản yêu cầu hành động rõ ràng của người dùng, phiên bản còn lại thì không.

Ảnh chụp màn hình hộp thoại Ảnh chụp màn hình hộp thoại
Hình 2. Xác thực khuôn mặt mà không có xác nhận của người dùng (ở trên cùng) và có xác nhận của người dùng (ở dưới cùng).

Đoạn mã sau đây cho thấy cách trình bày một hộp thoại mà không đòi hỏi người dùng phải thực hiện một hành động rõ ràng để hoàn tất quy trình xác thực:

Kotlin

// Lets the user authenticate without performing an action, such as pressing a
// button, after their biometric credential is accepted.
promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setNegativeButtonText("Use account password")
        .setConfirmationRequired(false)
        .build()

Java

// Lets the user authenticate without performing an action, such as pressing a
// button, after their biometric credential is accepted.
promptInfo = new BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setNegativeButtonText("Use account password")
        .setConfirmationRequired(false)
        .build();

Cho phép dự phòng thông tin xác thực phi sinh trắc học

Nếu muốn ứng dụng của mình cho phép xác thực bằng thông tin nhận dạng sinh trắc học hoặc thông tin xác thực thiết bị, bạn có thể khai báo rằng ứng dụng của bạn hỗ trợ thông tin xác thực thiết bị bằng cách đưa DEVICE_CREDENTIAL vào tập hợp giá trị mà bạn chuyển vào setAllowedAuthenticators().

Nếu ứng dụng của bạn đang sử dụng createConfirmDeviceCredentialIntent() hoặc setDeviceCredentialAllowed() để cung cấp tính năng này, hãy chuyển sang sử dụng setAllowedAuthenticators().

Tài nguyên khác

Để tìm hiểu thêm về tính năng xác thực bằng sinh trắc học trên Android, hãy tham khảo các tài nguyên sau.

Bài đăng trên blog