Вы интегрировали биометрию в Android-приложение, но на Xiaomi она не работает? Или используете устаревший FingerprintManager, который упадет на Android 14? Мы поможем реализовать надежную авторизацию по отпечатку пальца с использованием BiometricPrompt и CryptoObject. Решение под ключ с гарантией совместимости на всех брендах. Имеем 5+ лет опыта в мобильной разработке, реализовали биометрию в 30+ проектах. Стоимость интеграции под ключ — от 30 000 до 70 000 ₽ в зависимости от сложности.
Почему 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% сценариев и снижает затраты на интеграцию. Закажите реализацию биометрии прямо сейчас — мы подготовим коммерческое предложение в течение дня.







