日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

 

寫在前面

指紋識(shí)別大家都不陌生,現(xiàn)在比較新的Android/ target=_blank class=infotextkey>安卓手機(jī)大多都已經(jīng)支持面部識(shí)別了,指紋識(shí)別更是主流安卓手機(jī)的標(biāo)配功能。這兩個(gè)功能可以說用過都說好,確實(shí)是方便快捷。

不過大家觀察一下會(huì)發(fā)現(xiàn),這些手機(jī)的指紋識(shí)別和面部識(shí)別也就是支持一下手機(jī)的鎖屏解鎖而已,數(shù)量巨大的App對于這兩個(gè)技術(shù)的應(yīng)用可以說比較少。這何嘗不是APP良好體驗(yàn)性的損失呢?

慶幸的是,基于 google API 實(shí)現(xiàn)指紋識(shí)別的基礎(chǔ)性功能并不復(fù)雜。

指紋識(shí)別的兼容性和安全性問題

除了實(shí)現(xiàn)指紋識(shí)別的基礎(chǔ)性功能,我認(rèn)為開發(fā)者還需要關(guān)注和選擇性處理的問題有兩個(gè):兼容性和安全性。

為什么說選擇性處理?

首先說兼容性,指紋識(shí)別的 API 是 Google 在 Android 6.0 開放出來的。

在 Android 6.0 以下的系統(tǒng)上,某些手機(jī)廠商自行支持了指紋識(shí)別,如果我們的 APP 要兼容這些設(shè)備,就還要集成廠商的指紋識(shí)別的SDK,這是最大的兼容性問題。不過,現(xiàn)在 Android 6.0 以下的設(shè)備已經(jīng)很少了,其中支持指紋識(shí)別的設(shè)備就更少了,不對其進(jìn)行兼容,我認(rèn)為也是可以的。

在Android 6.0 以上的系統(tǒng)上,由于廠商對 Android 系統(tǒng)和指紋識(shí)別模塊的定制化普遍,導(dǎo)致會(huì)出現(xiàn)一些兼容性問題。這個(gè)沒有什么好的辦法,就需要開發(fā)者見招拆招了。已經(jīng)踩過坑的開發(fā)者很多,大家可以到網(wǎng)上搜索相關(guān)的文章看。

然后說下安全性,由于已添加的指紋是存儲(chǔ)在手機(jī)上的,Google API 驗(yàn)證指紋后僅僅返回 true 或者 false,我們是很難無條件相信這個(gè)識(shí)別結(jié)果的。比如說用戶的手機(jī) root 了或者是自定制設(shè)備,指紋識(shí)別是有可能被劫持進(jìn)而返回有誤的識(shí)別結(jié)果的。

好在這種情況發(fā)生的概率比較低。如果指紋識(shí)別的應(yīng)用場景非交易非支付,僅僅是類似于 “啟動(dòng) APP 進(jìn)行指紋驗(yàn)證” 這樣的情況的話,Google API 提供的指紋識(shí)別就夠用了。

關(guān)于兼容性和安全性的問題,本文不過多探討了,給大家推薦一篇文章,同時(shí)也請大家關(guān)注文章中提到的支付寶和騰訊的處理方式,及其開源情況:

指紋識(shí)別 API 的版本演進(jìn)

在 Android 6.0(Android M Api23),Android 系統(tǒng)開放了指紋識(shí)別的api,存在于 android.hardware.fingerprint包下,核心類是FingerprintManager,提供了基礎(chǔ)的指紋識(shí)別的功能。要注意的是,F(xiàn)ingerprintManager在 Android 9.0(Android P Api28)做了 @Deprecated 標(biāo)記,將被棄用。

后來,在android.support.v4.hardware.fingerprint包和 androidx.core.hardware.fingerprint包中,F(xiàn)ingerprintManager升級(jí)為了 FingerprintManagerCompat,對功能進(jìn)行了增強(qiáng),也做了一些兼容性的處理,比如增加了系統(tǒng)版本號(hào)的判斷,對指紋支持加密處理等。實(shí)際上閱讀源碼會(huì)發(fā)現(xiàn),他的核心功能還是調(diào)用 FingerprintManager 實(shí)現(xiàn)的。

再之后,在 Android 9.0(Android P Api 28),Google 對生物識(shí)別進(jìn)行了進(jìn)一步增強(qiáng),開放了以 BiometricPrompt 為核心的新 Api,存在于 androidx.biometric 包和android.hardware.biometrics包下,Google 在開發(fā)者文檔中是這樣解釋的:

On devices running P and above, this will show a system-provided authentication prompt, using a device's supported biometric (fingerprint, iris, face, etc).

大意是,在 Android P 及以上版本的系統(tǒng)中,BiometricPrompt 將展現(xiàn)一個(gè)由系統(tǒng)提供的驗(yàn)證提示,用于支持設(shè)備提供的生物識(shí)別,包括指紋、虹膜、面部等。

目前來看,虹膜和面部等生物識(shí)別 Api 尚未開放,僅支持指紋識(shí)別,不過在指紋識(shí)別上進(jìn)行了統(tǒng)一,比如要求使用統(tǒng)一的指紋識(shí)別 UI ,不允許開發(fā)者自定義了。

指紋識(shí)別關(guān)鍵方法 authenticate

這是指紋識(shí)別中最核心的方法,用于拉起指紋識(shí)別掃描器進(jìn)行指紋識(shí)別。

以 FingerprintManagerCompat 中 authenticate() 方法為例,開發(fā)者文檔中是這樣定義的:

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

 

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

解釋一下各個(gè)參數(shù):

  • FingerprintManagerCompat.CryptoObject crypto

源碼中是這樣解釋的:

 /**
 * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
 * framework supports {@link Signature} and {@link Cipher} objects.
 */

大意是,這是一個(gè)密碼對象的包裝類,當(dāng)前支持 Signature 形式和 Cipher 形式的密碼對象加密。

作用是,指紋掃描器會(huì)使用這個(gè)對象判斷指紋認(rèn)證結(jié)果的合法性。Android 6.0 是 @Nullable,但不建議傳 null,且在 Android 9.0 之后就是@NonNull 了。

我的代碼中提供了一個(gè) Cipher 的幫助類,可用來創(chuàng)建一個(gè) Cipher 對象,可參考使用。

  • int flags

可選標(biāo)志,暫無用處,傳 0 即可。只用于 Android 6.0。

  • CancellationSignal cancel

這個(gè)對象的作用是用來取消指紋掃描器的掃描操作。比如在用戶點(diǎn)擊識(shí)別框上的“取消”按鈕或者“密碼驗(yàn)證”按鈕后,就要及時(shí)取消掃描器的掃描操作。

不及時(shí)取消的話,指紋掃描器就會(huì)一直掃描,直至超時(shí)。這會(huì)造成兩個(gè)問題:

(1) 耗電

(2) 在超時(shí)時(shí)間內(nèi),用戶將無法再次調(diào)起指紋識(shí)別

同樣,這個(gè)參數(shù)在 Android 6.0 是 @Nullable,在 Android 9.0 之后是 @NonNull ,由于上述的原因,不建議傳 null 。

  • FingerprintManagerCompat.AuthenticationCallback callback

指紋識(shí)別結(jié)果的回調(diào)接口,是 @NonNull 的,其中聲明了如下幾個(gè)方法:

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

重點(diǎn)關(guān)注一下 onAuthenticationError() 和 onAuthenticationHelp() 兩個(gè)方法,當(dāng)出現(xiàn)指紋識(shí)別異常時(shí)會(huì)被回調(diào):

(1) 參數(shù) errString 和 helpString 是具體的異常信息,例如“手指移動(dòng)過快”、“驗(yàn)證失敗”等。這個(gè)異常信息是由系統(tǒng)提供的,目前看到的情況是系統(tǒng)會(huì)根據(jù)應(yīng)用使用的語言匹配對應(yīng)的異常信息。

應(yīng)用有做國際化的小伙伴,對系統(tǒng)匹配對應(yīng)語言的異常信息不放心的話,可根據(jù) errMsgId 和 helpMsgId 自行處理。

(2) 參數(shù) errMsgId 和 helpMsgId 是某個(gè)異常的 Id 標(biāo)識(shí),有很多,這里不贅述,各位請自行查看開發(fā)者文檔。注意注意的是,在 Android 6.0 上和 Android 9.0 上有差別。

  • Handler handler

這個(gè)參數(shù)用于 Android 6.0,是 @Nullable 的,作用是告訴系統(tǒng)使用這個(gè) Handler 的 Looper 處理指紋識(shí)別的 Message。默認(rèn)就是交給主線程的 Looper 處理,傳 null 即可。

  • Executor executor (補(bǔ)充,是)

這個(gè)參數(shù)是 Android 9.0 Api BiometricPrompt.authenticate() 中的參數(shù),是 @NonNull的,作用與上個(gè)參數(shù) Handler handler 類似,用來分發(fā)指紋識(shí)別的回調(diào)事件。

當(dāng)通過主線程進(jìn)行分發(fā)時(shí),可通過 Context#getMainExecutor() 傳參;

當(dāng)通過共享線程池進(jìn)行分發(fā)時(shí),可通過 AsyncTask#THREAD_POOL_EXECUTOR 傳參。

指紋識(shí)別的實(shí)踐

在指紋識(shí)別功能的實(shí)踐中,我將其做成了開源庫發(fā)布在了 Github 上,可通過 gradle 進(jìn)行依賴,使用方法比較簡單,兩三行代碼,再傳入一個(gè)驗(yàn)證結(jié)果監(jiān)聽即可。

下面對部分實(shí)現(xiàn)過程做一下介紹,詳細(xì)的 Api 及源碼請移步 Github。

Github 地址:https://github.com/ZuoHailong/BiometricPrompt

示例

Android 6.0 指紋識(shí)別框,開發(fā)者自定義:

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

Android 9.0 指紋識(shí)別框,系統(tǒng)提供:

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

其中指紋 icon 和取消按鈕的文字顏色,由屬性 colorPrimary 的顏色值決定。

指紋識(shí)別管理類

FingerprintVerifyManager 是指紋識(shí)別庫的入口,對指紋識(shí)別進(jìn)行管理,通過 FingerprintVerifyManager.Builder 對指紋識(shí)別進(jìn)行初始化。

在這個(gè)類中,有根據(jù)手機(jī)系統(tǒng)版本調(diào)用不同的指紋識(shí)別 Api(FingerprintManagerCompat或者 BiometricPrompt),其中 BiometricPrompt 支持開啟或者關(guān)閉,默認(rèn)關(guān)閉。

public FingerprintVerifyManager(Builder builder) {
 IFingerprint fingerprint;
 // >= Android P
 if (AndrVersionUtil.isAboveAndrP()) {
 //在 Android P 上是否展示系統(tǒng)提供的識(shí)別框
 if (builder.enableAndroidP)
 fingerprint = FingerprintAndrP.newInstance();
 else
 fingerprint = FingerprintAndrM.newInstance();
 } else if (AndrVersionUtil.isAboveAndrM()) {// Android 6.0 =< Version
 fingerprint = FingerprintAndrM.newInstance();
 } else {// < Android 6.0 ,官方未開放指紋識(shí)別,某些機(jī)型自行支持的情況暫不做處理
 builder.callback.onError(builder.context.getString(R.string.biometricprompt_verify_error_below_m));
 return;
 }
 ……
 fingerprint.authenticate(builder.context, bean, builder.callback);
 }

其中 IFingerprint 是指紋識(shí)別的接口,兼容 Android 6.0 的 FingerprintAndrM 和兼容 Android 9.0 的 FingerprintAndrP 都實(shí)現(xiàn)了此接口。

public interface IFingerprint {
 /**
 * 初始化并調(diào)起指紋識(shí)別
 *
 * @param context
 * @param verificationDialogStyleBean 指紋識(shí)別框樣式
 * @param callback 通知開發(fā)者指紋識(shí)別結(jié)果
 */
 void authenticate(Activity context, VerificationDialogStyleBean verificationDialogStyleBean, FingerprintCallback callback);
}

基于Android 6.0 實(shí)現(xiàn)指紋識(shí)別

上文有提及,F(xiàn)ingerprintAndrM 是基于 Android 6.0 的具體的指紋識(shí)別實(shí)現(xiàn)類:

@RequiresApi(api = Build.VERSION_CODES.M)
public class FingerprintAndrM implements IFingerprint {
 private final String TAG = FingerprintAndrM.class.getName();
 private Activity context;
 private static FingerprintAndrM fingerprintAndrM;
 //指紋驗(yàn)證框
 private static FingerprintDialog fingerprintDialog;
 //指向調(diào)用者的指紋回調(diào)
 private FingerprintCallback fingerprintCallback;
 //用于取消掃描器的掃描動(dòng)作
 private CancellationSignal cancellationSignal;
 //指紋加密
 private static FingerprintManagerCompat.CryptoObject cryptoObject;
 //Android 6.0 指紋管理
 private FingerprintManagerCompat fingerprintManagerCompat;
 @Override
 public void authenticate(Activity context, VerificationDialogStyleBean bean, FingerprintCallback callback) {
 //判斷指紋識(shí)別是否可用
 if (!canAuthenticate(context, callback))
 return;
 this.context = context;
 this.fingerprintCallback = callback;
 //Android 6.0 指紋管理 實(shí)例化
 fingerprintManagerCompat = FingerprintManagerCompat.from(context);
 //取消掃描,每次取消后需要重新創(chuàng)建新示例
 cancellationSignal = new CancellationSignal();
 cancellationSignal.setOnCancelListener(() -> fingerprintDialog.dismiss());
 //調(diào)起指紋驗(yàn)證
 fingerprintManagerCompat.authenticate(cryptoObject, 0, cancellationSignal, authenticationCallback, null);
 //指紋驗(yàn)證框
 fingerprintDialog = FingerprintDialog.newInstance(context).setActionListener(dialogActionListener).setDialogStyle(bean);
 fingerprintDialog.show(context.getFragmentManager(), TAG);
 }
 public static FingerprintAndrM newInstance() {
 if (fingerprintAndrM == null) {
 synchronized (FingerprintAndrM.class) {
 if (fingerprintAndrM == null) {
 fingerprintAndrM = new FingerprintAndrM();
 }
 }
 }
 //指紋加密,提前進(jìn)行Cipher初始化,防止指紋認(rèn)證時(shí)還沒有初始化完成
 try {
 cryptoObject = new FingerprintManagerCompat.CryptoObject(new CipherHelper().createCipher());
 } catch (Exception e) {
 e.printStackTrace();
 }
 return fingerprintAndrM;
 }
 /**
 * 指紋驗(yàn)證框按鍵監(jiān)聽
 */
 private FingerprintDialog.OnDialogActionListener dialogActionListener = new FingerprintDialog.OnDialogActionListener() {
 @Override
 public void onUsepwd() {
 if (fingerprintCallback != null)
 fingerprintCallback.onUsepwd();
 }
 @Override
 public void onCancle() {//取消指紋驗(yàn)證,通知調(diào)用者
 if (fingerprintCallback != null)
 fingerprintCallback.onCancel();
 }
 @Override
 public void onDismiss() {//驗(yàn)證框消失,取消指紋驗(yàn)證
 if (cancellationSignal != null && !cancellationSignal.isCanceled())
 cancellationSignal.cancel();
 }
 };
 /**
 * 指紋驗(yàn)證結(jié)果回調(diào)
 */
 private FingerprintManagerCompat.AuthenticationCallback authenticationCallback = new FingerprintManagerCompat.AuthenticationCallback() {
 @Override
 public void onAuthenticationError(int errMsgId, CharSequence errString) {
 super.onAuthenticationError(errMsgId, errString);
 fingerprintDialog.setTip(errString.toString(), R.color.biometricprompt_color_FF5555);
 }
 @Override
 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
 super.onAuthenticationHelp(helpMsgId, helpString);
 fingerprintDialog.setTip(helpString.toString(), R.color.biometricprompt_color_FF5555);
 }
 @Override
 public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
 super.onAuthenticationSucceeded(result);
 fingerprintDialog.setTip(context.getString(R.string.biometricprompt_verify_success), R.color.biometricprompt_color_82C785);
 fingerprintCallback.onSucceeded();
 fingerprintDialog.dismiss();
 }
 @Override
 public void onAuthenticationFailed() {
 super.onAuthenticationFailed();
 fingerprintDialog.setTip(context.getString(R.string.biometricprompt_verify_failed), R.color.biometricprompt_color_FF5555);
 fingerprintCallback.onFailed();
 }
 };
 /*
 * 在 Android Q,Google 提供了 Api BiometricManager.canAuthenticate() 用來檢測指紋識(shí)別硬件是否可用及是否添加指紋
 * 不過尚未開放,標(biāo)記為"Stub"(存根)
 * 所以暫時(shí)還是需要使用 Andorid 6.0 的 Api 進(jìn)行判斷
 * */
 private boolean canAuthenticate(Context context, FingerprintCallback fingerprintCallback) {
 /*
 * 硬件是否支持指紋識(shí)別
 * */
 if (!FingerprintManagerCompat.from(context).isHardwareDetected()) {
 fingerprintCallback.onError(FingerprintManager.FINGERPRINT_ERROR_HW_NOT_PRESENT, context.getString(R.string.biometricprompt_verify_error_no_hardware));
 return false;
 }
 //是否已添加指紋
 if (!FingerprintManagerCompat.from(context).hasEnrolledFingerprints()) {
 fingerprintCallback.onNoneEnrolled();
 return false;
 }
 return true;
 }
}

這里面要重點(diǎn)關(guān)注 CancellationSignal 與指紋識(shí)別框的關(guān)聯(lián),也就是識(shí)別框消失,就一定要取消指紋掃描器的掃描操作,否則在超時(shí)時(shí)間內(nèi),用戶將無法再次拉起指紋識(shí)別(盡管可以彈出指紋識(shí)別框)。

基于Android 9.0 實(shí)現(xiàn)指紋識(shí)別

上文有提及,F(xiàn)ingerprintAndrP 是基于 Android 9.0 的具體的指紋識(shí)別實(shí)現(xiàn)類:

@RequiresApi(api = Build.VERSION_CODES.P)
public class FingerprintAndrP implements IFingerprint {
 private static FingerprintAndrP fingerprintAndrP;
 //指向調(diào)用者的指紋回調(diào)
 private FingerprintCallback fingerprintCallback;
 //用于取消掃描器的掃描動(dòng)作
 private CancellationSignal cancellationSignal;
 //指紋加密
 private static BiometricPrompt.CryptoObject cryptoObject;
 @Override
 public void authenticate(Activity context, VerificationDialogStyleBean verificationDialogStyleBean, FingerprintCallback callback) {
 //判斷指紋識(shí)別是否可用
 if (!canAuthenticate(context, callback))
 return;
 this.fingerprintCallback = callback;
 /*
 * 初始化 BiometricPrompt.Builder
 */
 ……
 //構(gòu)建 BiometricPrompt
 BiometricPrompt biometricPrompt = builder.build();
 //取消掃描,每次取消后需要重新創(chuàng)建新示例
 cancellationSignal = new CancellationSignal();
 cancellationSignal.setOnCancelListener(() -> {
 });
 /*
 * 拉起指紋驗(yàn)證模塊,等待驗(yàn)證
 * Executor:
 * context.getMainExecutor()
 */
 biometricPrompt.authenticate(cryptoObject, cancellationSignal, context.getMainExecutor(), authenticationCallback);
 }
 public static FingerprintAndrP newInstance() {
 if (fingerprintAndrP == null) {
 synchronized (FingerprintAndrM.class) {
 if (fingerprintAndrP == null) {
 fingerprintAndrP = new FingerprintAndrP();
 }
 }
 }
 //指紋加密,提前進(jìn)行Cipher初始化,防止指紋認(rèn)證時(shí)還沒有初始化完成
 try {
 cryptoObject = new BiometricPrompt.CryptoObject(new CipherHelper().createCipher());
 } catch (Exception e) {
 e.printStackTrace();
 }
 return fingerprintAndrP;
 }
 /**
 * 認(rèn)證結(jié)果回調(diào)
 */
 private BiometricPrompt.AuthenticationCallback authenticationCallback = new BiometricPrompt.AuthenticationCallback() {
 @Override
 public void onAuthenticationError(int errorCode, CharSequence errString) {
 super.onAuthenticationError(errorCode, errString);
 if (fingerprintCallback != null) {
 if (errorCode == 5) {//用戶取消指紋驗(yàn)證,不必向用戶拋提示信息
 fingerprintCallback.onCancel();
 return;
 }
 fingerprintCallback.onError(errorCode, errString.toString());
 }
 }
 @Override
 public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
 super.onAuthenticationHelp(helpCode, helpString);
 if (fingerprintCallback != null)
 fingerprintCallback.onError(helpCode, helpString.toString());
 }
 @Override
 public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
 super.onAuthenticationSucceeded(result);
 if (fingerprintCallback != null)
 fingerprintCallback.onSucceeded();
 }
 @Override
 public void onAuthenticationFailed() {
 super.onAuthenticationFailed();
 if (fingerprintCallback != null)
 fingerprintCallback.onFailed();
 }
 };
 /*
 * 在 Android Q,Google 提供了 Api BiometricManager.canAuthenticate() 用來檢測指紋識(shí)別硬件是否可用及是否添加指紋
 * 不過尚未開放,標(biāo)記為"Stub"(存根)
 * 所以暫時(shí)還是需要使用 Andorid 6.0 的 Api 進(jìn)行判斷
 * */
 private boolean canAuthenticate(Context context, FingerprintCallback fingerprintCallback) {
 /*
 * 硬件是否支持指紋識(shí)別
 * */
 if (!FingerprintManagerCompat.from(context).isHardwareDetected()) {
 fingerprintCallback.onError(FingerprintManager.FINGERPRINT_ERROR_HW_NOT_PRESENT, context.getString(R.string.biometricprompt_verify_error_no_hardware));
 return false;
 }
 //是否已添加指紋
 if (!FingerprintManagerCompat.from(context).hasEnrolledFingerprints()) {
 fingerprintCallback.onNoneEnrolled();
 return false;
 }
 return true;
 }
}

這里需要開發(fā)者關(guān)注的有兩點(diǎn):

(1) Android 9.0 不允許開發(fā)者自定義指紋識(shí)別框,但系統(tǒng)提供的指紋識(shí)別框的靈活性堪憂。比如說,目前來看,系統(tǒng)只允許在識(shí)別框出現(xiàn)一個(gè)按鈕,放了 “取消” 就不能放 “密碼驗(yàn)證” ,放了 “密碼驗(yàn)證” 就不能放 “取消”。(尷尬臉……)

(2) 系統(tǒng)提供的指紋識(shí)別框只能在界面底部,不可以上下居中。但在某些手機(jī)上(如OPPO reno),指紋傳感器也是在界面底部,當(dāng)拉起指紋識(shí)別時(shí),會(huì)在指紋傳感器的位置顯示一個(gè)指紋圖標(biāo),以提示用戶在哪下指。然而,系統(tǒng)提供的指紋識(shí)別框上也有一個(gè)指紋圖標(biāo),這兩個(gè)指紋圖標(biāo)就發(fā)生了重合或者離的很近。(尷尬臉……)

示例:

Android指紋識(shí)別,提升APP用戶體驗(yàn),從這里開始

 

鑒于以上問題,指紋開源庫提供了一個(gè)方法 builder.enableAndroidP(boolean enableAndroidP) ,允許調(diào)用者開啟或者關(guān)閉 Android 9.0 系統(tǒng)提供的指紋識(shí)別框。當(dāng)關(guān)閉時(shí),將使用 Android 6.0 的指紋識(shí)別 Api,并使用自定義的指紋識(shí)別框。

指紋識(shí)別庫 Github 地址:https://github.com/ZuoHailong/BiometricPrompt

最后

如果你看到了這里,覺得文章寫得不錯(cuò)就給個(gè)贊唄?如果你覺得那里值得改進(jìn)的,請給我留言。一定會(huì)認(rèn)真查詢,修正不足。謝謝。

分享到:
標(biāo)簽:指紋識(shí)別 Android
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定