說明
指紋認證一般我們期望是這樣的:
- 指紋支付可以和手指綁定,比和微信支付一樣:開啟時輸入一個指紋,每次支付的時候只能用當(dāng)時綁定的指紋支付,這樣可以保證指紋安全。
- 如果上面的走不通的話,那就只能和招商銀行指紋登錄一樣:開啟指紋登錄時驗證指紋,驗證通過之后,以后每次登錄都可以通過驗證輸入的指紋是否是錄入系統(tǒng)中的任何一個指紋。 如果你開通指紋后,又在系統(tǒng)中錄入了新的指紋,下次用指紋登錄招商銀行的時候就會被提示指紋發(fā)生了變化。
我個人調(diào)研指紋認證方案主要是下面兩種:
- 使用微信開源Soter庫
這個方案的優(yōu)點就是穩(wěn),據(jù)說微信的指紋支付就是使用的這個方案,和國產(chǎn)設(shè)備廠商合作的.可以定位的具體的哪個手指,可以獲取到指紋Id. 不足之處就是不支持華為手機和國外部分廠商(沒有和Soter合作的). 雖然微信客戶端是支持華為指紋的.但是這個框架是暫時不支持的.(很久之前就說要支持,截至目前仍未支持)
- 使用系統(tǒng)官方Api
優(yōu)點:支持所有android 6.0以上的指紋設(shè)備(招商銀行80%可能性使用的就是這個方案)
-
缺點:
- 不能獲取指紋Id,不能和手指綁定,同能通過判斷指紋庫是否變化保證安全
- 需要針對android 6.0 和android 9.0 適配 : android 9.0 以下需要自己實現(xiàn)指紋識別彈窗樣式 ,但是android 9.0 開始統(tǒng)一由系統(tǒng)彈窗實現(xiàn)(不同廠商可能還不一樣)
綜合考慮我們選擇使用系統(tǒng)官方Api實現(xiàn)第二種方案,只支持所有android 6.0 以上的指紋設(shè)備
效果演示
- android M
-
指紋識別成功
m-success.gif -
指紋驗證失敗
m-fail.gif -
指紋數(shù)據(jù)發(fā)生了改變
m-change.gif
- android P
-
指紋識別成功
p-success.gif -
指紋驗證失敗
p-fail.gif -
指紋數(shù)據(jù)發(fā)生了改變
p-change.gif
快速集成
在項目下的build.gradle文件中
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
在app下的build.gradle文件中
implementation 'com.github.LambdaXiao:BiometricManager:v1.1.0'
具體使用如下:
findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
switch (FingerManager.checkSupport(MainActivity.this)) {
case DEVICE_UNSUPPORTED:
showToast("您的設(shè)備不支持指紋");
break;
case SUPPORT_WITHOUT_DATA:
showToast("請在系統(tǒng)錄入指紋后再驗證");
break;
case SUPPORT:
FingerManager.build().setApplication(getApplication())
.setTitle("指紋驗證")
.setDes("請按下指紋")
.setNegativeText("取消")
// .setFingerDialogApi23(new MyFingerDialog())//如果你需要自定義android P 以下系統(tǒng)彈窗就設(shè)置,注意需要繼承BaseFingerDialog,不設(shè)置會使用默認彈窗
.setFingerCallback(new SimpleFingerCallback() {
@Override
public void onSucceed() {
showToast("驗證成功");
}
@Override
public void onFailed() {
showToast("指紋無法識別");
}
@Override
public void onChange() {
showToast("指紋數(shù)據(jù)發(fā)生了變化");
}
})
.create()
.startListener(MainActivity.this);
break;
default:
}
}
}
});
支持功能
- 檢查設(shè)備是否支持指紋:分為三種支持,分別是(1)設(shè)備沒有指紋識別器 (2)設(shè)備有指紋識別器但是沒有指紋數(shù)據(jù)(3)設(shè)備有識別器并且有指紋數(shù)據(jù),可以進行指紋驗證
- 監(jiān)聽相應(yīng)手機指紋庫數(shù)據(jù)發(fā)生變化的情況
- 指紋數(shù)據(jù)發(fā)生變化后可以調(diào)用updateFingerData()方法更新同步變化
- 能夠?qū)θ∠讣y識別和指紋識別失敗分別進行處理
- 需要適配android版本,在android版本大于6.0 小于9.0 的情況下要自己實現(xiàn)指紋識別彈窗。在android P上要使用最新Api調(diào)用指紋識別統(tǒng)一彈窗
如何監(jiān)聽指紋數(shù)據(jù)變化
- 創(chuàng)建SecretKey對當(dāng)前指紋數(shù)據(jù)加密,如果在創(chuàng)建SecretKey后添加新指紋,則會在Cipher初始化時引發(fā)KeyPermanentlyInvalidatedException.通過這個異常我們可以知道指紋數(shù)據(jù)是否發(fā)生變化
/**
* @des 初始化Cipher ,根據(jù)KeyPermanentlyInvalidatedExceptiony異常判斷指紋庫是否發(fā)生了變化
*
*/
public boolean initCipher(Cipher cipher) {
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEYSTORE_ALIAS, null);
if (cipher == null) {
cipher = createCipher();
}
cipher.init(Cipher.ENCRYPT_MODE, key);
return false;
} catch (KeyPermanentlyInvalidatedException e) {
//指紋庫是否發(fā)生了變化,這里會拋KeyPermanentlyInvalidatedException
return true;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
- 唯一例外的是三星手機不會拋出KeyPermanentlyInvalidatedException這個異常,經(jīng)過反復(fù)測試,發(fā)現(xiàn)三星手機可以根據(jù)識別成功后的回調(diào)方法中檢測cipher.doFinal(SECRET_MESSAGE.getBytes())這里的異常判斷指紋數(shù)據(jù)是否發(fā)生變化
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Cipher cipher = result.getCryptoObject().getCipher();
if (cipher != null) {
try {
/*
* 用于檢測三星手機指紋庫變化,
* 三星手機指紋庫發(fā)生變化后前面的initCipher檢測不到KeyPermanentlyInvalidatedException
* 但是cipher.doFinal(SECRET_MESSAGE.getBytes())會拋出異常
* 因此以此監(jiān)聽三星手機的指紋庫變化
*/
cipher.doFinal(SECRET_MESSAGE.getBytes());
cancel.cancel();
mFingerDialog.onSucceed();
mFingerCallback.onSucceed();
} catch (Exception e) {
e.printStackTrace();
mFingerCallback.onChange();
}
}
自定義android 9.0以下彈窗
如果你想自定義android M 的指紋識別彈窗,很簡單,你只需要:
- 繼承BaseFingerDialog類
- 在onCreateView中初始化你自己的布局
- 實現(xiàn)onSucceed()、onFailed()、onHelp()、onError()四個回調(diào)就好了,這四個回調(diào)建議只做UI相關(guān)操作,邏輯操作已經(jīng)在外部提供了回調(diào)接口。
- onSucceed :指紋識別成功,可以直接關(guān)閉彈窗
- onFailed : 當(dāng)識別的手指沒有注冊時回調(diào),但是可以繼續(xù)驗證
- onHelp : 指紋識別不對,會提示,手指不要大范圍移動等信息,可以繼續(xù)驗證
- onError :指紋識別徹底失敗,不能繼續(xù)驗證
- 一個指紋識別事件序列是這樣的: 開始識別 ---> (onHelp / onFaild) (0個或多個) ---> onSucceed / onError
調(diào)起指紋識別得時候,將自定義的彈窗設(shè)置進去,代碼如下,如果你不設(shè)置自定義彈窗會使用默認的android M 彈窗
FingerManager.build().setApplication(getApplication())
.setTitle("指紋驗證")
.setDes("請按下指紋")
.setNegativeText("取消")
.setFingerDialogApi23(new MyFingerDialog())
.setFingerCheckCallback()
最后貼出github鏈接:https://github.com/LambdaXiao/BiometricManager
參考鏈接
https://github.com/googlearchive/android-FingerprintDialog
https://android.ctolib.com/mengcuiguang-FingerDemo.html





