指紋登錄 - FingerprintManager

最近項目中添加了一個新的登錄方式:指紋識別。好巧不巧這塊分給了我,然后一頓研究。下面想把一些實現的代碼貼出來做個筆記,加深下印象。
先來介紹下指紋識別,指紋識別是Google從Android6.0(api23)開始才提供的標準指紋識別支持,并對外提供指紋識別相關的接口。

一開始我在理解指紋識別的時候有幾個誤區:
①我認為指紋識別,哇,這么高大上,應該是一個第三方的SDK,需要引入第三方來做,就和我們做刷臉識別引入了百度的SDK一樣。后來發現是我想復雜了,指紋識別是Android6.0以上就開始支持的一個功能,并且類也不多,主要就是FingerprintManager還有它里面三個內部類(AuthenticationCallback、AuthenticationResult、CryptoObject),后面細講。

②我認為指紋識別應該是在自己的APP里面既能錄入又能識別,把指紋數據放到APP的儲存中。后來發現也不是我想的那樣,首先明確的一點是指紋數據是在手機的設置里面,不是存到自己寫的APP的。其次,指紋識別就只能識別,而不能在APP中錄入指紋,想錄入指紋可以,自己要到手機設置里面的指紋功能自己去添加,指紋識別功能能做的就是把用戶放到感應區的指紋數據與手機設置里面的已錄入的指紋數據進行比對,再執行成功失敗的回調,僅此而已。

③我認為指紋識別會很難。其實不然,如果你只是要指紋的識別結果,而不是深入的研究它的加密了(CryptoObject),指紋列表的變化監聽(這個大致說一下啥意思,在一些場景中,需要對用戶手機里面錄入的指紋進行監聽,當用戶手機里面的指紋列表發生了變化,比如用戶刪除了指紋或者新增了指紋,就需要用戶重新輸入密碼,這就需要指紋變化的監聽,記錄用戶手機里面的指紋 ID,并進行前后對比,才能實現。這種情況在APP中很常見,拿支付寶說,我本來手機中只錄入了我右手的食指指紋,我習慣右手玩手機,但后來我又錄入了左手的食指指紋,這時候我再使用支付寶的指紋付款,它就會彈出我的支付密碼框,讓我輸入我的支付密碼),它就沒多少東西,像我們項目中,只是對指紋做了個比對,把結果拿到而已,那就非常簡單。話不多說,下面直接上代碼。


指紋開啟前提

這里插一嘴,介紹一下FingerprintManager類,它是Google提供的幫助訪問指紋硬件的API類,主要有三個方法:


三個主要的方法

第一個方法:啟動指紋識別(先稍作忽略,后面講)
第二個方法:判斷手機里面是否有已經有錄入的指紋(至少得有一個)
第三個方法:判斷手機是否有指紋感應區(硬件支持)
ok 繼續!

①檢查權限
Android清單文件中的指紋的權限是

<uses-permission android:name="android.permission.USE_FINGERPRINT"/>

你查資料就會發現這個權限它是NormalPermissions,它不是DangerousPermissions 按理說不用考慮6.0的動態權限問題,只要在清單文件中添加一下即可。但是Android廠家定制的系統很多很多,可能有些系統不一定會默認分配指紋權限,比如上幾篇中文章中那款傻逼vivo6.0的動態權限,簡直就是胡改瞎改。以防萬一,還是檢查下吧,以防萬一!

@NeedsPermission(Manifest.permission.USE_FINGERPRINT)
void showFingerDilaog(){
    //去開啟指紋識別操作
}

@OnNeverAskAgain(Manifest.permission.USE_FINGERPRINT)
void showNeverAskForCall() {
    //點擊了不再詢問按鈕的回調
    //低版本手機不支持指紋識別的也會走這個回調
}

@OnPermissionDenied(Manifest.permission.USE_FINGERPRINT)
void showRefuseForCall() {
     //點擊了禁止按鈕的回調
}

我把項目中檢測權限的代碼貼到這里(算是偽代碼吧,只看邏輯即可),我們用到的是PermissionsDispatcher來檢測動態權限問題的,當然,關于動態權限的框架很多,像我前幾篇文章的那個RXPermissions也是一種辦法,這里動態權限方法挑適合自己的即可。

②檢查手機硬件(有沒有指紋感應區)

if (!mManager.isHardwareDetected()) {
    Toast.makeText(mContext, "沒有指紋識別模塊", Toast.LENGTH_SHORT).show();
    return false;
}

這個mManager就是FingerprintManager對象,用上面圖片中它的第三個方法即可判斷,很簡單,沒什么可說的

③檢查手機是否開啟鎖屏密碼
為什么要檢查這個呢?因為Android6.0以上的手機添加指紋前,必須要先啟鎖屏密碼,以免不能使用指紋時,用戶還可以采用其他方法打開手機。

if (!mKeyManager.isKeyguardSecure()) {
    Toast.makeText(mContext(), "沒有開啟鎖屏密碼", Toast.LENGTH_SHORT).show();
    return false;
}

這個mKeyManager就是KeyguardManager的對象,它的作用就是對Keyguard進行管理,即對鎖屏進行管理。在這里它的作用只是判斷用戶手機是否設置了鎖屏密碼。

④檢查手機是否已錄入指紋
這個很好理解,指紋識別,手機里總得先有指紋供檢測吧。

if (!mManager.hasEnrolledFingerprints()) {
    Toast.makeText(mContext, "沒有指紋錄入", Toast.LENGTH_SHORT).show();
    return false;
}

這個是上面圖片中它的第二個方法。好了,到這里,我們把上面的幾個方法結合一起,就能寫出一個完整的手機指紋識別開啟的檢測條件:

@TargetApi(23)
public boolean judgeFingerprintIsCorrect() {
    //判斷硬件是否支持指紋識別
    if (!mManager.isHardwareDetected()) {
        Toast.makeText(mContext, "沒有指紋識別模塊", Toast.LENGTH_SHORT).show();
        return false;
    }
    //判斷是否開啟鎖屏密碼
    if (!mKeyManager.isKeyguardSecure()) {
        Toast.makeText(mContext, "沒有開啟鎖屏密碼", Toast.LENGTH_SHORT).show();
        return false;
    }
    //判斷是否有指紋錄入
    if (!mManager.hasEnrolledFingerprints()) {
        Toast.makeText(mContext, "沒有指紋錄入", Toast.LENGTH_SHORT).show();
        return false;
    }
    return true;
}

這里需要注意一下,FingerprintManager對象的isHardwareDetected()方法和hasEnrolledFingerprints()方法需要API級別為23及以上,如果你的API級別小于23,那就得加上@TargetApi(23)

創建指紋開啟的回調方法

這里就該引入上面所說的FingerprintManager的三個內部類了

①FingerPrintManager.AuthenticationCallback:
在驗證時傳入該接口,通過該接口來返回驗證指紋的結果

②FingerPrintManager.AuthenticationResult:
當指紋驗證正確時,接口里返回的參數

③FingerPrintManager.CryptoObject:
由FingerPrintManager支持的封裝加密對象的類

上面我們說到,如果你只要指紋識別的結果,其他的功能不關系,那就很簡單,只要和AuthenticationCallback類打交道即可。這一步我們就創建AuthenticationCallback類對象,上代碼

FingerprintManager.AuthenticationCallback mSelfCancelled = new FingerprintManager.AuthenticationCallback() {
    @Override
    public void onAuthenticationError(int errorCode, CharSequence errString) {
        //多次指紋密碼驗證錯誤后,進入此方法;并且,不可再驗(短時間)
        //errorCode是失敗的次數
        ToastUtils.show(mContext, "嘗試次數過多,請稍后重試", 3000);
    }

    @Override
    public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
        //指紋驗證失敗,可再驗,可能手指過臟,或者移動過快等原因。
    }

    @Override
    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
        //指紋密碼驗證成功
    }

    @Override
    public void onAuthenticationFailed() {
        //指紋驗證失敗,指紋識別失敗,可再驗,錯誤原因為:該指紋不是系統錄入的指紋。
    }
};

開啟指紋識別

接下來,我們將指紋識別的CallBack綁定到FingerprintManager中,以獲得指紋識別的結果。這就得引入上面圖片中FingerprintManager的第一個方法:

/**
 * 參數說明:
 * FingerprintManager.CryptoObject - 用于通過指紋驗證取出AndroidKeyStore中的key的對象,用于加密
 * CancellationSignal - 用來取消指紋驗證,如果想手動關閉驗證,可以調用該參數的cancel方法
 * int - 沒什么意義,就是傳0就好了
 * FingerprintManager.AuthenticationCallback -  最重要,由于指紋信息是存在系統硬件中的,app是不可以訪問指紋信息的,所以每次驗證的時候,系統會通過這個callback告訴你是否驗證通過、驗證失敗等
 * Handler - FingerPrint中的消息都通過這個Handler來傳遞消息,如果你傳空,則默認創建一個在主線程上的Handler來傳遞消息,沒什么用,傳null好了
 */
public void authenticate(FingerprintManager.CryptoObject crypto, CancellationSignal cancel, int flags, FingerprintManager.AuthenticationCallback callback, Handler handler)

像我們項目中的代碼如下:

mManager.authenticate(null, mCancellationSignal, 0, mSelfCancelled, null);

可以看到,這個方法中傳遞了一個AuthenticationCallback,用于獲取指紋識別結果 ,傳遞了一個CancellationSignal(后面再說)。OK,至此,指紋識別已經開啟了。

取消指紋識別

當我們指紋識別完了,拿到我們想要的結果了,那我們要怎么樣取消指紋識別呢?
這就需要用到CancellationSignal 類了,就是我們上面代碼中的第二個參數。上代碼:

CancellationSignal mCancellationSignal = new CancellationSignal();

...

mManager.authenticate(null, mCancellationSignal, 0, mSelfCancelled, null);

...

//取消指紋識別
mCancellationSignal.cancel();

可以看出取消指紋識別很簡單,authenticate方法中的第二個參數是一個CancellationSignal對象,這個對象就是用來維護取消操作的,這些操作包括取消監聽和設定取消回調等。所以,如果要取消,這個參數就不能傳Null。
這里補充一點哈,當執行取消指紋識別之后

//取消指紋識別
mCancellationSignal.cancel();

會執行的回調方法是:

onAuthenticationError()

也就是說,手動取消指紋識別,和多次驗證失敗走的方法是一樣的。


簡單的指紋識別應用到此就說的差不多了,當然,這只是簡單應用而已。指紋這塊還有很多很多東西等著我們去學習。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容