Ви інтегрували біометрію в Android-додаток, але на Xiaomi вона не працює? Або використовуєте застарілий FingerprintManager, який впаде на Android 14? Ми допоможемо реалізувати надійну авторизацію за відбитком пальця з використанням BiometricPrompt та CryptoObject. Рішення під ключ з гарантією сумісності на всіх брендах. Маємо 5+ років досвіду в мобільній розробці, реалізували біометрію в 30+ проектах. Вартість інтеграції визначається після аналізу вашого проекту.
Чому BiometricPrompt кращий за FingerprintManager?
FingerprintManager (deprecated з API 28) підтримує лише відбиток, не працює з CryptoObject і нестабільний на кастомних прошивках. BiometricPrompt з бібліотеки androidx.biometric (працює з API 23+) підтримує відбиток, обличчя, райдужку, а головне — дозволяє прив'язати аутентифікацію до криптографічного ключа через CryptoObject. Це підвищує безпеку до рівня Class 3 (Strong) — найнадійнішої категорії біометрії в Android.
| Параметр | FingerprintManager | BiometricPrompt |
|---|---|---|
| Мінімальний API | 23 (тільки відбиток) | 23 (androidx), 28 (нативний) |
| Підтримка модальностей | Відбиток | Відбиток, обличчя, райдужка |
| CryptoObject | Ні | Так |
| Стійкість до підробки | Слабка (Class 2) | Сильна (Class 3) |
| Сумісність з MIUI | Проблематична | Стабільна при правильному fallback |
Які типові помилки трапляються?
Помилка 1: виклик з ViewModel
BiometricPrompt вимагає передачі FragmentActivity або Fragment. Розробники іноді намагаються викликати його з ViewModel або Repository — отримують IllegalStateException у рантаймі. Prompt живе в UI-шарі, крапка. Якщо вам потрібно ініціювати аутентифікацію з бізнес-логіки, використовуйте callback або Event-підхід.
Помилка 2: відсутність CryptoObject
Багато реалізацій викликають BiometricPrompt.authenticate() без CryptoObject, тобто перевіряють лише наявність біометрії, але не прив'язують її до криптографічної операції. Це "слабка" біометрія: зловмисник з root-доступом теоретично може підробити результат аутентифікації, інжектуючи SUCCESS в AuthenticationCallback. Правильний шлях — Class 3 (Strong) біометрія з CryptoObject. Як зазначено в документації Android, лише CryptoObject забезпечує криптографічне зв'язування аутентифікації з операцією шифрування.
Помилка 3: фрагментація Android
На MIUI 12–13 BiometricManager.canAuthenticate(BIOMETRIC_STRONG) повертає BIOMETRIC_ERROR_NONE_ENROLLED навіть при зареєстрованих відбитках через кастомізацію Xiaomi. Доводиться додавати fallback-перевірку через FingerprintManagerCompat для таких випадків. Ми гарантуємо коректну роботу на пристроях Samsung, Xiaomi, Pixel та інших — протестовано на 20+ моделях.
Правильна реалізація з CryptoObject
Генерація ключа в Android Keystore
Суть: генеруємо ключ в Android Keystore, прив'язаний до біометрії. При аутентифікації Cipher ініціалізується цим ключем і передається в CryptoObject. Якщо біометрія пройшла успішно — cipher розблокований і можна шифрувати/розшифровувати дані.
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) .build() ) keyGenerator.generateKey() setInvalidatedByBiometricEnrollment(true) — ключ інвалідується при додаванні нового відбитка. Без цього прапора старий ключ залишається робочим після зміни біометрії користувачем, що знижує безпеку.
Ініціалізація Cipher та CryptoObject
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}") val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } val secretKey = keyStore.getKey(KEY_NAME, null) as SecretKey cipher.init(Cipher.ENCRYPT_MODE, secretKey) val cryptoObject = BiometricPrompt.CryptoObject(cipher) Потім передаємо cryptoObject в biometricPrompt.authenticate(promptInfo, cryptoObject).
Callback обов'язково обробляємо повністю
object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { val cipher = result.cryptoObject?.cipher ?: return // розшифровуємо токен з EncryptedSharedPreferences } override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { when (errorCode) { BiometricPrompt.ERROR_LOCKOUT -> showFallback() BiometricPrompt.ERROR_LOCKOUT_PERMANENT -> showPermanentLockout() BiometricPrompt.ERROR_NEGATIVE_BUTTON -> showPinAuth() BiometricPrompt.ERROR_USER_CANCELED -> { /* нічого не робимо */ } } } override fun onAuthenticationFailed() { // спроба не вдалася, але ліміт не вичерпано — BiometricPrompt сам показує помилку } } onAuthenticationFailed — не фінальна помилка. Система сама оновлює UI промпта. Не ховайте промпт і не показуйте свої помилки в цьому callback.
Зберігання токена
Використовуємо EncryptedSharedPreferences з androidx.security:security-crypto. Шифруємо token через cipher з успішного CryptoObject, зберігаємо зашифровані байти + IV в EncryptedSharedPreferences. При наступній авторизації: розгортаємо біометрію в режимі DECRYPT_MODE зі збереженим IV → отримуємо plaintext токен.
Процес роботи
| Етап | Тривалість |
|---|---|
| Аналіз та проектування | 1 день |
| Реалізація KeyStore-ключа та CryptoObject-flow | 1–2 дні |
| UI промпта з кастомними текстами | 0.5 дня |
| Обробка всіх error-кодів | 0.5 дня |
| Тестування на реальних пристроях (Samsung, Xiaomi, Pixel) | 1–2 дні |
| Покриття unit-тестами | 1 день |
Що входить в роботу
- Документація по інтеграції
- Вихідний код з коментарями
- Інструкція по збірці та підпису
- Підтримка протягом 30 днів після здачі
- Гарантія сумісності з Android 6.0+ та брендами Xiaomi, Samsung, Huawei
Оцінимо ваш проект протягом 1 дня. Зв'яжіться з нами для консультації — допоможемо з вибором підходящого підходу. Отримайте безкоштовну оцінку термінів та вартості.
Покрокова інструкція по інтеграції
- Встановіть залежність
androidx.biometric:biometric:1.2.0-alpha05. - Створіть ключ в Android Keystore з параметрами з прикладу вище.
- Ініціалізуйте Cipher та CryptoObject.
- Налаштуйте BiometricPrompt.PromptInfo з заголовком та підзаголовком.
- Викличте
biometricPrompt.authenticate(promptInfo, cryptoObject). - Обробіть callback — розшифруйте токен при
onAuthenticationSucceeded. - Для зберігання використовуйте EncryptedSharedPreferences.
Додатково: якщо ви хочете заощадити на розробці, зверніть увагу на нашу типову реалізацію — вона покриває 90% сценаріїв і знижує витрати на інтеграцію. Замовте реалізацію біометрії прямо зараз — ми підготуємо комерційну пропозицію протягом дня.







