Như chúng ta đã biết, hầu hết các thiết bị di động Android hiện nay đều hỗ trợ các phương thức bảo mật, đặc biệt phổ biến là tính năng xác thực bằng vân tay. Nếu bạn đang muốn tích hợp tính năng nhận diện vân tay vào ứng dụng của mình, bài viết này sẽ cung cấp cho bạn 5 bước đơn giản để làm điều đó. Theo thông báo chính thức từ Google, họ đã hỗ trợ nhận diện vân tay trên Android từ phiên bản Android 6.0 (M) trở đi. Sử dụng API BiometricPrompt, bạn có thể tận dụng tiện ích và đảm bảo tính chính xác cũng như cấp độ bảo mật cao. Dưới đây là 5 bước cần thiết để tích hợp tính năng thú vị này vào ứng dụng của bạn.
Bước 1: Thêm permissions vào file AndroidManifest.xml
Trong file AndroidManifest.xml của ứng dụng, bạn cần thêm các quyền sau:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.an.biometric">
<!-- Bước 1: Thêm quyền sau vào ứng dụng -->
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<!-- Bước 2: Quyền này đã bị deprecated trong Android P -->
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
</manifest>
Bước 2: Kiểm tra hỗ trợ xác thực vân tay trên thiết bị
Các điều kiện kiểm tra như sau:
- Thiết bị phải chạy Android phiên bản >= 6.0 (Marshmallow).
- Thiết bị phải có cảm biến vân tay.
- Người dùng đã cấp quyền sử dụng cảm biến vân tay cho ứng dụng hay chưa.
- Người dùng đã bật tính năng vân tay và đăng ký dấu vân tay trước đó. Bạn có thể tạo một file Utils để kiểm tra như sau:
public class BiometricUtils {
public static boolean isBiometricPromptEnabled() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P);
}
public static boolean isSdkVersionSupported() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
}
public static boolean isHardwareSupported(Context context) {
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(context);
return fingerprintManager.isHardwareDetected();
}
public static boolean isFingerprintAvailable(Context context) {
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(context);
return fingerprintManager.hasEnrolledFingerprints();
}
public static boolean isPermissionGranted(Context context) {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED;
}
}
Bước 3: Hiển thị Dialog BiometricPrompt
Khi tất cả các điều kiện trên đều thỏa mãn, ta sẽ hiển thị một Dialog để xác thực vân tay. Cách hiển thị như sau:
@TargetApi(Build.VERSION_CODES.P)
private void displayBiometricPrompt(final BiometricCallback biometricCallback) {
new BiometricPrompt.Builder(context)
.setTitle(title) // Tiêu đề dialog (bắt buộc)
.setSubtitle(subtitle) // Tiêu đề phụ bên dưới (tùy chọn)
.setDescription(description) // Mô tả nội dung (tùy chọn)
.setNegativeButton(negativeButtonText, context.getMainExecutor(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
biometricCallback.onAuthenticationCancelled();
}
})
.build();
}
Bước 4: Xử lí Callback
Ta sử dụng callback BiometricPrompt.AuthenticationCallback để lắng nghe phản hồi từ người dùng sau khi xác thực vân tay. Callback trả về 4 phương thức chính:
- onAuthenticationSucceeded: Khi nhận diện vân tay thành công.
- onAuthenticationFailed: Khi không xác định được vân tay nào khớp với dữ liệu trong hệ thống.
- onAuthenticationError: Khi có lỗi xác thực vân tay.
- onAuthenticationHelp: Khi có lỗi không nghiêm trọng, ví dụ như vân tay bị dơ, người dùng di chuyển quá nhanh... Mã lỗi cụ thể có thể được tìm thấy trong tài liệu.
@RequiresApi(api = Build.VERSION_CODES.P)
public class BiometricCallbackV28 extends BiometricPrompt.AuthenticationCallback {
private BiometricCallback biometricCallback;
public BiometricCallbackV28(BiometricCallback biometricCallback) {
this.biometricCallback = biometricCallback;
}
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
biometricCallback.onAuthenticationSuccessful();
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
super.onAuthenticationHelp(helpCode, helpString);
biometricCallback.onAuthenticationHelp(helpCode, helpString);
}
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
biometricCallback.onAuthenticationError(errorCode, errString);
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
biometricCallback.onAuthenticationFailed();
}
}
Nếu thiết bị của bạn chạy Android P trở lên, chúc mừng bạn đã thành công. Nhưng nếu không, chúng ta phải làm gì?
Điều gì xảy ra nếu thiết bị không hỗ trợ Android P?
Tất cả các phiên bản Android dưới Android P sẽ không sử dụng được API BiometricPrompt. Nhưng không sao, ta vẫn có thể sử dụng API FingerprintManagerCompat để xác thực người dùng bằng vân tay. Bạn cần làm như sau:
- Sử dụng Keystore và generating key: Android cho phép lưu trữ các khóa mã hóa bằng cách làm cho chúng khó truy cập từ thiết bị. Việc này cũng hạn chế cách thức và thời gian mà mỗi khóa có thể sử dụng. Khi khóa được tạo, nó sẽ được lưu trữ an toàn trên thiết bị bằng cách sử dụng keystore và sử dụng để tạo đối tượng cipher trong bước tiếp theo.
private void generateKey() {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (KeyStoreException | NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException | CertificateException | IOException exc) {
exc.printStackTrace();
}
}
- Khởi tạo cipher: Việc khởi tạo cipher này sẽ được sử dụng để tạo instance CryptoObject. Trong quá trình khởi tạo cipher, khóa được tạo và khóa lưu trữ trong keystore sẽ được sử dụng.
private boolean initCipher() {
try {
Cipher cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/" +
KeyProperties.BLOCK_MODE_CBC + "/" +
KeyProperties.ENCRYPTION_PADDING_PKCS7
);
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException |
IOException | NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
- Tạo CryptoObject: Bộ quản lý vân tay sẽ sử dụng CryptoObject để giúp xác thực và đưa ra kết quả.
FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
- Gán CryptoObject cho FingerprintManagerCompat:
FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(context);
fingerprintManagerCompat.authenticate(cryptoObject, 0, new CancellationSignal(), new FingerprintManagerCompat.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
super.onAuthenticationError(errMsgId, errString);
updateStatus(String.valueOf(errString));
biometricCallback.onAuthenticationError(errMsgId, errString);
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
super.onAuthenticationHelp(helpMsgId, helpString);
updateStatus(String.valueOf(helpString));
biometricCallback.onAuthenticationHelp(helpMsgId, helpString);
}
@Override
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
dismissDialog();
biometricCallback.onAuthenticationSuccessful();
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
updateStatus(context.getString(R.string.biometric_failed));
biometricCallback.onAuthenticationFailed();
}
}, null);
Phương thức authenticate yêu cầu các thông số sau:
- cryptoObject
- Tham số thứ hai luôn là 0, đây là một flag được định nghĩa trong Android Document, có thể được sử dụng trong tương lai.
- Tham số thứ ba là đối tượng CancellationSignal, dùng để tắt scanner và huỷ yêu cầu hiện tại.
- Tham số thứ tư là một lớp con của AuthenticationCallback, tương tự như BiometricAuthenticationCallback.
- Tham số thứ năm là một optional Handler. Nếu cung cấp Handler, FingerprintManager sẽ sử dụng Looper từ Handler đó để xử lý các tin nhắn từ phần cứng vân tay.
- Tạo giao diện tương tự Dialog BiometricPrompt: Bạn có thể tạo một Dialog tùy chỉnh theo ý thích của mình.
public class BiometricDialogV23 extends BottomSheetDialog implements View.OnClickListener {
// ...
}
Đó là 5 bước để tích hợp tính năng xác thực vân tay vào ứng dụng Android của bạn. Hy vọng rằng bài chia sẻ sẽ mang lại giá trị cho bạn và sẽ là hướng dẫn hữu ích khi bạn gặp vấn đề về tích hợp xác thực vân tay. Cảm ơn bạn đã đọc và hẹn gặp lại.
Tham khảo: https://proandroiddev.com/5-steps-to-implement-biometric-authentication-in-android-dbeb825aeee8