1、介紹
指紋登錄可以實現(xiàn)應(yīng)用的快捷登錄,在Android6.0谷歌才提供統(tǒng)一指紋SDK接口,在6.0之前都是各個廠商自定義。
2、使用
下面介紹如何在我們的應(yīng)用中加入指紋登錄的功能,之前實現(xiàn)指紋解鎖都是用的FingerprintManager類,F(xiàn)ingerprintManager在最新的Android 9.0系統(tǒng)上已經(jīng)被廢棄了,當(dāng)Google在v4包中把FingerprintManager改為了FingerprintManagerCompat,而Compat是兼容的意思,所以Google在v4包中做了一些兼容性處理,官方推薦使用后者。所以本demo用的就是FingerprintManagerCompat工具類。
一、申請權(quán)限
<!-- 指紋權(quán)限 -->
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
二、驗證手機(jī)是否支持指紋,如果手機(jī)不支持,那就沒辦法了。
FingerprintManagerCompat提供了三個方法:
- isHardwareDetected() 判斷是否有硬件支持
- isKeyguardSecure() 判斷是否設(shè)置鎖屏,因為一個手機(jī)最少要有兩種登錄方式
- hasEnrolledFingerprints() 判斷系統(tǒng)中是否添加至少一個指紋
/**
* 判斷是否支持指紋識別
*/
public static boolean supportFingerprint(Context mContext) {
if (Build.VERSION.SDK_INT < 23) {
Toast.makeText(mContext, "您的系統(tǒng)版本過低,不支持指紋功能", Toast.LENGTH_SHORT).show();
return false;
} else {
KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(mContext);
if (!fingerprintManager.isHardwareDetected()) {
Toast.makeText(mContext, "您的系統(tǒng)版本過低,不支持指紋功能", Toast.LENGTH_SHORT).show();
return false;
} else if (keyguardManager != null && !keyguardManager.isKeyguardSecure()) {
Toast.makeText(mContext, "您的手機(jī)不支持指紋功能", Toast.LENGTH_SHORT).show();
return false;
} else if (!fingerprintManager.hasEnrolledFingerprints()) {
Toast.makeText(mContext, "您至少需要在系統(tǒng)設(shè)置中添加一個指紋", Toast.LENGTH_SHORT).show();
return false;
}
}
return true;
}
三、開啟指紋登錄,一般來說都是彈出個提示框用于顯示指紋識別的狀態(tài)。
首先,生成一個對稱加密的key
private static final String DEFAULT_KEY_NAME = "default_key";
@TargetApi(23)
private void initKey() {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
keyGenerator.init(builder.build());
keyGenerator.generateKey();
initCipher(keyStore);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
然后,通過生成的key初始化生成一個Cipher對象
@TargetApi(23)
private void initCipher(KeyStore keyStore) {
try {
SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null);
Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
cipher.init(Cipher.ENCRYPT_MODE, key);
showFingerPrintDialog(cipher);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
最后,通過上面生成的Cipher去開啟指紋驗證
private void showFingerPrintDialog(Context context, Cipher cipher) {
FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(context);
FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
CancellationSignal mCancellationSignal = new CancellationSignal();
//識別過程中可以手動取消指紋識別
//mCancellationSignal.cancel();
fingerprintManagerCompat.authenticate(cryptoObject, 0, mCancellationSignal, new MyCallBack(), null);
}
下面詳細(xì)說一下,剛才開啟指紋驗證的時候的步驟:
1、創(chuàng)建一個FingerprintManagerCompat對象,上面有說到谷歌已經(jīng)不推薦使用FingerprintManager類。
FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(context);
2、拿到FingerprintManagerCompat對象后就可以調(diào)authenticate方法進(jìn)行指紋識別了,這里面需要傳遞幾個參數(shù):
(1)CryptoObject 這是一個加密類的對象,指紋掃描器會使用這個對象來判斷認(rèn)證結(jié)果的合法性。這個對象可以是null,但是這樣的話,就意味這app無條件信任認(rèn)證的結(jié)果,雖然從理論上這個過程可能被攻擊,數(shù)據(jù)可以被篡改,這是app在這種情況下必須承擔(dān)的風(fēng)險。因此,建議這個參數(shù)不要置為null。這里就需要使用之前初始化的Cipher去創(chuàng)建一個CryptoObject 對象。
FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
(2)flags 標(biāo)識位,這個標(biāo)志位應(yīng)該是保留將來使用的,在這里我們傳0就可以了。
(3)cancel這個是CancellationSignal類的一個對象,這個對象用來在指紋識別器掃描用戶指紋的是時候取消當(dāng)前的掃描操作,如果不取消的話,那么指紋掃描器會移植掃描直到超時(一般為30s,取決于具體的廠商實現(xiàn)),這樣的話就會比較耗電。建議這個參數(shù)不要置為null。識別過程中可以手動取消指紋識別。
CancellationSignal mCancellationSignal = new CancellationSignal();
//識別過程中可以手動取消指紋識別
//mCancellationSignal.cancel();
(4)callback這個參數(shù)很重要,看名字就知道這是個回調(diào)的接口,這個參數(shù)等最后我們詳細(xì)來介紹。這個參數(shù)不能為null。
(5)handler這是Handler類的對象,F(xiàn)ingerprintManagerCompat將會使用這個handler中的looper來處理來自指紋識別硬件的消息。一般來說,我們開發(fā)的時候可以直接傳null,因為FingerprintManagerCompat會默認(rèn)使用app的main looper來處理。
3、最后我們來說一下剛才的callback這個參數(shù)
public class MyCallBack extends FingerprintManagerCompat.AuthenticationCallback {
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
//當(dāng)出現(xiàn)錯誤的時候回調(diào)此函數(shù),比如多次嘗試都失敗了的時候,errString是錯誤信息
//一般來說我們都是先判斷一下是不是自己手動取消
Log.e("TAG", "errMsgId=" + errMsgId);
if (errMsgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
Log.e("TAG", "" + errString);
}
}
//當(dāng)指紋驗證失敗的時候會回調(diào)此函數(shù),失敗之后允許多次嘗試,失敗次數(shù)過多會停止響應(yīng)一段時間然后再停止sensor的工作
@Override
public void onAuthenticationFailed() {
//指紋認(rèn)證失敗,請再試一次
Log.e("TAG", "onAuthenticationFailed");
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
//錯誤時提示幫助,比如說指紋錯誤,我們將顯示在界面上 讓用戶知道情況
Log.e("TAG", "helpString=" + helpString);
}
//當(dāng)驗證的指紋成功時會回調(diào)此函數(shù),然后不再監(jiān)聽指紋sensor
@Override
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
//這里我們可以做取消彈框之類的
Log.e("TAG", "onAuthenticationSucceeded=" + result.toString());
}
}
四、總結(jié)
以上就是一個開發(fā)指紋識別的基本過程,希望對大家有所幫助。。。