שילבתם ביומטריה באפליקציית אנדרואיד, אבל זה לא עובד על שיאומי? או משתמשים ב-FingerprintManager המיושן שיתרסק על אנדרואיד 14? אנחנו עוזרים ליישם אימות טביעת אצבע אמין עם BiometricPrompt ו-CryptoObject. פתרון סוהר עם אחריות תאימות לכל המותגים. יש לנו ניסיון של 5+ שנים בפיתוח מובייל ויישמנו ביומטריה ביותר מ-30 פרויקטים. עלות השילוב נקבעת לאחר ניתוח—צרו קשר לקבלת הצעת מחיר.
למה BiometricPrompt עדיף על FingerprintManager?
FingerprintManager (מיושן מאז API 28) תומך רק בטביעת אצבע, לא עובד עם CryptoObject, ולא יציב על ROMs מותאמים. BiometricPrompt מהספרייה androidx.biometric (עובד מ-API 23+) תומך בטביעת אצבע, פנים, קשתית—והכי חשוב, מאפשר לקשור אימות למפתח קריפטוגרפי דרך CryptoObject. זה מעלה את האבטחה ל-Class 3 (Strong)—הקטגוריה הביומטרית הגבוהה ביותר באנדרואיד.
| פרמטר | FingerprintManager | BiometricPrompt |
|---|---|---|
| API מינימלי | 23 (טביעת אצבע בלבד) | 23 (androidx), 28 (native) |
| תמיכה במצבי זיהוי | טביעת אצבע | טביעת אצבע, פנים, קשתית |
| CryptoObject | לא | כן |
| עמידות לזיוף | חלשה (Class 2) | חזקה (Class 3) |
| תאימות MIUI | בעייתית | יציבה עם fallback מתאים |
טעויות נפוצות
טעות 1: קריאה מ-ViewModel
BiometricPrompt דורש FragmentActivity או Fragment. מפתחים לפעמים מנסים לקרוא לו מ-ViewModel או Repository ומקבלים IllegalStateException בזמן ריצה. ה-prompt חי בשכבת ה-UI, נקודה. אם צריך ליזום אימות מהלוגיקה העסקית, השתמשו ב-callbacks או בגישה מבוססת אירועים.
טעות 2: חוסר CryptoObject
יישומים רבים קוראים ל-BiometricPrompt.authenticate() ללא CryptoObject, כלומר הם רק בודקים נוכחות ביומטרית אבל לא קושרים אותה לפעולה קריפטוגרפית. זו ביומטריה "חלשה": תוקף עם גישת root יכול theoretically להזריק SUCCESS לתוך AuthenticationCallback. הגישה הנכונה היא ביומטריה Class 3 (Strong) עם CryptoObject. לפי תיעוד אנדרואיד, רק CryptoObject מספק קישור קריפטוגרפי של האימות לפעולת ההצפנה.
טעות 3: פרגמנטציה של אנדרואיד
ב-MIUI 12–13, BiometricManager.canAuthenticate(BIOMETRIC_STRONG) מחזיר BIOMETRIC_ERROR_NONE_ENROLLED אפילו עם טביעות אצבע רשומות בגלל ההתאמה האישית של שיאומי. צריך להוסיף בדיקת fallback באמצעות FingerprintManagerCompat למקרים כאלה. אנחנו מבטיחים פעולה תקינה על סמסונג, שיאומי, 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()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() —המפתח נפסל כאשר נרשמת טביעת אצבע חדשה. ללא דגל זה, המפתח הישן נשאר תקף לאחר שהמשתמש משנה ביומטריה, מה שמפחית את האבטחה.
אתחול 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)לאחר מכן העבירו את setInvalidatedByBiometricEnrollment(true) ל-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) .
טיפול מלא ב-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 сам показывает ошибку
}
}cryptoObject אינו שגיאה סופית. המערכת מעדכנת את ממשק ה-prompt בעצמה. אל תסתירו את ה-prompt ואל תציגו שגיאות משלכם ב-callback הזה.
אחסון טוקנים
השתמשו ב-biometricPrompt.authenticate(promptInfo, cryptoObject) מ-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 сам показывает ошибку } } . הצפינו את הטוקן באמצעות ה-cipher מאימות CryptoObject מוצלח, אחסנו את הבייטים המוצפנים + IV ב-onAuthenticationFailed. באימות הבא: אתחלו ביומטריה ב-EncryptedSharedPreferences עם ה-IV השמור → קבלו טוקן בטקסט רגיל.
תהליך עבודה
| שלב | משך |
|---|---|
| ניתוח ועיצוב | יום אחד |
| יישום מפתח Keystore וזרימת CryptoObject | 1–2 ימים |
| ממשק Prompt עם טקסט מותאם | 0.5 יום |
| טיפול בכל קודי השגיאה | 0.5 יום |
| בדיקות על מכשירים אמיתיים (סמסונג, שיאומי, Pixel) | 1–2 ימים |
| כיסוי בדיקות יחידה | יום אחד |
מה כלול
- תיעוד שילוב
- קוד מקור עם הערות
- הוראות בנייה וחתימה
- תמיכה ל-30 יום לאחר המסירה
- אחריות תאימות לאנדרואיד 6.0+ ולמותגים (שיאומי, סמסונג, Huawei)
נעריך את הפרויקט שלכם תוך יום אחד. צרו קשר לייעוץ—נעזור לכם לבחור את הגישה הנכונה. קבלו לוח זמנים והערכת עלות.
מדריך שילוב שלב-אחר-שלב
- הוסיפו תלות
androidx.security:security-crypto. - צרו מפתח ב-Android Keystore עם הפרמטרים מהדוגמה למעלה.
- אתחלו Cipher ו-CryptoObject.
- הגדירו BiometricPrompt.PromptInfo עם כותרת וכותרת משנה.
- קראו ל-
EncryptedSharedPreferences. - טפלו ב-callback—פענחו את הטוקן ב-
DECRYPT_MODE. - לאחסון, השתמשו ב-EncryptedSharedPreferences.
בנוסף, אם אתם רוצים לחסוך בפיתוח, שקלו את היישום הסטנדרטי שלנו—הוא מכסה 90% מהתרחישים ומפחית את עלויות השילוב. הזמינו יישום ביומטרי עכשיו—נכין הצעה מסחרית תוך יום.







