Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 6.0指紋識別App開發案例

Android 6.0指紋識別App開發案例

編輯:關於Android編程

在android 6.0中google終於給android系統加上了指紋識別的支持,這個功能在iPhone上早就已經實現了,並且在很多廠商的定制的ROM中也都自己內部實現這個功能了,這個功能來的有點晚啊。在google全新發布的nexus設備:nexus 5x和nexus 6p中都攜帶了一顆指紋識別芯片在設備的背面,如下圖(圖片來自網絡):

筆者手中的設備就是圖上的那台黑色的nexus 5x,話說這台機器很是好看呢!手感超棒!
廢話不多說,下面我出一個指紋識別的demo app,並且詳細說明怎麼開發一個基於google api的指紋識別app。demo的源碼在我的github上:
https://github.com/CreateChance/AndroidFingerPrintDemo

Android M中的指紋識別接口

這個是首先需要關注的問題,在實際動手開始寫app之前需要知道最新的平台為我們提供了那些指紋識別的接口。所有的指紋識別接口全部在android.hardware.fingerprint這個包下,這個包中的類不是很多,如下:

api doc鏈接地址:
https://developer.android.com/reference/android/hardware/fingerprint/package-summary.html
大家最好FQ自己看下。
上面的圖中,我們看到這個包中總共有4個類,下面我們簡要介紹一下他們:
1.FingerprintManager:主要用來協調管理和訪問指紋識別硬件設備
2.FingerprintManager.AuthenticationCallback這個一個callback接口,當指紋認證後系統會回調這個接口通知app認證的結果是什麼
3.FingerprintManager.AuthenticationResult這是一個表示認證結果的類,會在回調接口中以參數給出
4.FingerprintManager.CryptoObject這是一個加密的對象類,用來保證認證的安全性,這是一個重點,下面我們會分析。
好了,到這裡我們簡要知道了android 6.0給出的指紋識別的接口不是很多,可以說是簡短干練。

動手開發一個指紋識別app

現在,我們要動手寫一個利用上面接口的指紋識別app,這個app界面很簡單,就一個activity,這個activity上會激活指紋識別,然後提示用戶按下指紋,並且會將認證的結果顯示出來。

開始

在開始之前,我們需要知道使用指紋識別硬件的基本步驟:
1.在AndroidManifest.xml中申明如下權限:

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

2.獲得FingerprintManager的對象引用
3.在運行是檢查設備指紋識別的兼容性,比如是否有指紋識別設備等。下面我們詳細說一下上面的步驟:

申明權限

這一步比較簡單,只要在AndroidManifest.xml中添加上面說到的權限就可以了。

獲得FingerprintManager對象引用

這是app開發中獲得系統服務對象的常用方式,如下:

// Using the Android Support Library v4
fingerprintManager = FingerprintManagerCompat.from(this);
// Using API level 23:
fingerprintManager = (FingerprintManager)getSystemService(Context.FINGERPRINT_SERVICE);

上面給出兩種方式,第一種是通過V4支持包獲得兼容的對象引用,這是google推行的做法;還有就是直接使用api 23 framework中的接口獲得對象引用。

檢查運行條件

要使得我們的指紋識別app能夠正常運行,有一些條件是必須滿足的。

1). API level 23
指紋識別API是在api level 23也就是android 6.0中加入的,因此我們的app必須運行在這個系統版本之上。因此google推薦使用 Android Support Library v4包來獲得FingerprintManagerCompat對象,因為在獲得的時候這個包會檢查當前系統平台的版本。

2). 硬件
指紋識別肯定要求你的設備上有指紋識別的硬件,因此在運行時需要檢查系統當中是不是有指紋識別的硬件:

if (!fingerprintManager.isHardwareDetected()) {
 // no fingerprint sensor is detected, show dialog to tell user.
 AlertDialog.Builder builder = new AlertDialog.Builder(this);
 builder.setTitle(R.string.no_sensor_dialog_title);
 builder.setMessage(R.string.no_sensor_dialog_message);
 builder.setIcon(android.R.drawable.stat_sys_warning);
 builder.setCancelable(false);
 builder.setNegativeButton(R.string.cancel_btn_dialog, new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
   finish();
  }
 });
 // show this dialog.
 builder.create().show();
}

調用上面的接口接可以知道系統中是不是有一個這樣的硬件,如果沒有的話,那就需要做一些合適的事情,比如提示用戶當前系統中沒有指紋識別硬件等。

3). 當前設備必須是處於安全保護中的
這個條件的意思是,你的設備必須是使用屏幕鎖保護的,這個屏幕鎖可以是password,PIN或者圖案都行。為什麼是這樣呢?因為google原生的邏輯就是:想要使用指紋識別的話,必須首先使能屏幕鎖才行,這個和android 5.0中的smart lock邏輯是一樣的,這是因為google認為目前的指紋識別技術還是有不足之處,安全性還是不能和傳統的方式比較的。
我們可以使用下面的代碼檢查當前設備是不是處於安全保護中的:

KeyguardManager keyguardManager =(KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager.isKeyguardSecure()) {
 // this device is secure.
}

我們使用KeyguardManager的isKeyguardSecure接口就能知道。

4). 系統中是不是有注冊的指紋
在android 6.0中,普通app要想使用指紋識別功能的話,用戶必須首先在setting中注冊至少一個指紋才行,否則是不能使用的。所以這裡我們需要檢查當前系統中是不是已經有注冊的指紋信息了:

if (!fingerprintManager.hasEnrolledFingerprints()) {
 // no fingerprint image has been enrolled.
 AlertDialog.Builder builder = new AlertDialog.Builder(this);
 builder.setTitle(R.string.no_fingerprint_enrolled_dialog_title);
 builder.setMessage(R.string.no_fingerprint_enrolled_dialog_message);
 builder.setIcon(android.R.drawable.stat_sys_warning);
 builder.setCancelable(false);
 builder.setNegativeButton(R.string.cancel_btn_dialog, new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
   finish();
  }
 });
 // show this dialog
 builder.create().show();
}

如果用戶還沒有注冊一個指紋的話,那麼我們的app可以提示用戶:如果想要使用指紋是功能,請再setting中注冊一個你的指紋。這裡需要啰嗦一句,如果你做過bluetooth或者其他設備開發的話,那麼你知道你可以通過發送一個intent來啟動bluetooth開啟的界面,只要是聲明了藍牙的管理權限。但是,到目前位置google任然沒有開放讓普通app啟動指紋注冊界面的權限,這一點我們可以從setting的AndroidManifest中看到:

<activity android:name=".fingerprint.FingerprintSettings" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollOnboard" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollFindSensor" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollEnrolling" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollFinish" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollIntroduction" android:exported="false" />

<activity android:name=".fingerprint.SetupFingerprintEnrollOnboard" android:exported="false"/>
<activity android:name=".fingerprint.SetupFingerprintEnrollFindSensor" android:exported="false"/>
<activity android:name=".fingerprint.SetupFingerprintEnrollEnrolling" android:exported="false"/>
<activity android:name=".fingerprint.SetupFingerprintEnrollFinish" android:exported="false"/>
<activity android:name=".fingerprint.SetupFingerprintEnrollIntroduction"
 android:exported="true"
 android:permission="android.permission.MANAGE_FINGERPRINT"
 android:theme="@style/SetupWizardDisableAppStartingTheme">
 <intent-filter>
  <action android:name="android.settings.FINGERPRINT_SETUP" />
  <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>
</activity>

大部分的fingerprint設置界面都沒有exporte,只有SetupFingerprintEnrollIntroduction,但是這個界面需要android.permission.MANAGE_FINGERPRINT這個權限,並且這個權限只能是系統app使用,這就直接防止第三方app啟動這個界面了。(不知道日後google會不會開放這個權限。。。。。)

一個好的app,應該在運行時都檢查一下上面的條件,防止app出現意外的錯誤。

掃描用戶按下的指紋

要開始掃描用戶按下的指紋是很簡單的,只要調用FingerprintManager的authenticate方法即可,那麼現在我們來看一下這個接口:

上圖是google的api文檔中的描述,現在我們挨個解釋一下這些參數都是什麼:
1. crypto這是一個加密類的對象,指紋掃描器會使用這個對象來判斷認證結果的合法性。這個對象可以是null,但是這樣的話,就意味這app無條件信任認證的結果,雖然從理論上這個過程可能被攻擊,數據可以被篡改,這是app在這種情況下必須承擔的風險。因此,建議這個參數不要置為null。這個類的實例化有點麻煩,主要使用javax的security接口實現,後面我的demo程序中會給出一個helper類,這個類封裝內部實現的邏輯,開發者可以直接使用我的類簡化實例化的過程。
2. cancel 這個是CancellationSignal類的一個對象,這個對象用來在指紋識別器掃描用戶指紋的是時候取消當前的掃描操作,如果不取消的話,那麼指紋掃描器會移植掃描直到超時(一般為30s,取決於具體的廠商實現),這樣的話就會比較耗電。建議這個參數不要置為null。
3. flags 標識位,根據上圖的文檔描述,這個位暫時應該為0,這個標志位應該是保留將來使用的。
4. callback 這個是FingerprintManager.AuthenticationCallback類的對象,這個是這個接口中除了第一個參數之外最重要的參數了。當系統完成了指紋認證過程(失敗或者成功都會)後,會回調這個對象中的接口,通知app認證的結果。這個參數不能為NULL。
5. handler 這是Handler類的對象,如果這個參數不為null的話,那麼FingerprintManager將會使用這個handler中的looper來處理來自指紋識別硬件的消息。通常來講,開發這不用提供這個參數,可以直接置為null,因為FingerprintManager會默認使用app的main looper來處理。

取消指紋掃描

上面我們提到了取消指紋掃描的操作,這個操作是很常見的。這個時候可以使用CancellationSignal這個類的cancel方法實現:

這個方法專門用於發送一個取消的命令給特定的監聽器,讓其取消當前操作。
因此,app可以在需要的時候調用cancel方法來取消指紋掃描操作。

創建CryptoObject類對象

上面我們分析FingerprintManager的authenticate方法的時候,看到這個方法的第一個參數就是CryptoObject類的對象,現在我們看一下這個對象怎麼去實例化。
我們知道,指紋識別的結果可靠性是非常重要的,我們肯定不希望認證的過程被一個第三方以某種形式攻擊,因為我們引入指紋認證的目的就是要提高安全性。但是,從理論角度來說,指紋認證的過程是可能被第三方的中間件惡意攻擊的,常見的攻擊的手段就是攔截和篡改指紋識別器提供的結果。這裡我們可以提供CryptoObject對象給authenticate方法來避免這種形式的攻擊。
FingerprintManager.CryptoObject是基於Java加密API的一個包裝類,並且被FingerprintManager用來保證認證結果的完整性。通常來講,用來加密指紋掃描結果的機制就是一個Javax.Crypto.Cipher對象。Cipher對象本身會使用由應用調用Android keystore的API產生一個key來實現上面說道的保護功能。
為了理解這些類之間是怎麼協同工作的,這裡我給出一個用於實例化CryptoObject對象的包裝類代碼,我們先看下這個代碼是怎麼實現的,然後再解釋一下為什麼是這樣。

public class CryptoObjectHelper
{
 // This can be key name you want. Should be unique for the app.
 static final String KEY_NAME = "com.createchance.android.sample.fingerprint_authentication_key";

 // We always use this keystore on Android.
 static final String KEYSTORE_NAME = "AndroidKeyStore";

 // Should be no need to change these values.
 static final String KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
 static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
 static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
 static final String TRANSFORMATION = KEY_ALGORITHM + "/" +
 BLOCK_MODE + "/" +
 ENCRYPTION_PADDING;
 final KeyStore _keystore;

 public CryptoObjectHelper() throws Exception
 {
  _keystore = KeyStore.getInstance(KEYSTORE_NAME);
  _keystore.load(null);
 }

 public FingerprintManagerCompat.CryptoObject buildCryptoObject() throws Exception
 {
  Cipher cipher = createCipher(true);
  return new FingerprintManagerCompat.CryptoObject(cipher);
 }

 Cipher createCipher(boolean retry) throws Exception
 {
  Key key = GetKey();
  Cipher cipher = Cipher.getInstance(TRANSFORMATION);
  try
  {
   cipher.init(Cipher.ENCRYPT_MODE | Cipher.DECRYPT_MODE, key);
  } catch(KeyPermanentlyInvalidatedException e)
  {
   _keystore.deleteEntry(KEY_NAME);
   if(retry)
   {
    createCipher(false);
   } else
   {
    throw new Exception("Could not create the cipher for fingerprint authentication.", e);
   }
  }
  return cipher;
 }

 Key GetKey() throws Exception
 {
  Key secretKey;
  if(!_keystore.isKeyEntry(KEY_NAME))
  {
   CreateKey();
  }

  secretKey = _keystore.getKey(KEY_NAME, null);
  return secretKey;
 }

 void CreateKey() throws Exception
 {
  KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM, KEYSTORE_NAME);
  KeyGenParameterSpec keyGenSpec =
    new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
      .setBlockModes(BLOCK_MODE)
      .setEncryptionPaddings(ENCRYPTION_PADDING)
      .setUserAuthenticationRequired(true)
      .build();
  keyGen.init(keyGenSpec);
  keyGen.generateKey();
 }
}

上面的類會針對每個CryptoObject對象都會新建一個Cipher對象,並且會使用由應用生成的key。這個key的名字是使用KEY_NAME變量定義的,這個名字應該是保證唯一的,建議使用域名區別。GetKey方法會嘗試使用Android Keystore的API來解析一個key(名字就是上面我們定義的),如果key不存在的話,那就調用CreateKey方法新建一個key。
cipher變量的實例化是通過調用Cipher.getInstance方法獲得的,這個方法接受一個transformation參數,這個參數制定了數據怎麼加密和解密。然後調用Cipher.init方法就會使用應用的key來完成cipher對象的實例化工作。
這裡需要強調一點,在以下情況下,android會認為當前key是無效的:
1. 一個新的指紋image已經注冊到系統中
2. 當前設備中的曾經注冊過的指紋現在不存在了,可能是被全部刪除了
3. 用戶關閉了屏幕鎖功能
4. 用戶改變了屏幕鎖的方式
當上面的情況發生的時候,Cipher.init方法都會拋出KeyPermanentlyInvalidatedException的異常,上面我的代碼中捕獲了這個異常,並且刪除了當前無效的key,然後根據參數嘗試再次創建。
上面的代碼中使用了android的KeyGenerator來創建一個key並且把它存儲在設備中。KeyGenerator類會創建一個key,但是需要一些原始數據才能創建key,這些原始的信息是通過KeyGenParameterSpec類的對象來提供的。KeyGenerator類對象的實例化是使用它的工廠方法getInstance進行的,從上面的代碼中我們可以看到這裡使用的AES(Advanced Encryption Standard )加密算法的,AES會將數據分成幾個組,然後針對幾個組進行加密。
接下來,KeyGenParameterSpec的實例化是使用它的Builder方法,KeyGenParameterSpec.Builder封裝了以下重要的信息:
1. key的名字
2. key必須在加密和解密的時候是有效的
3. 上面代碼中BLOCK_MODE被設置為Cipher Block Chaining也就是KeyProperties.BLOCK_MODE_CBC,這意味著每一個被AES切分的數據塊都與之前的數據塊進行了異或運算了,這樣的目的就是為了建立每個數據塊之間的依賴關系。
4. CryptoObjectHelper類使用了PKSC7(Public Key Cryptography Standard #7)的方式去產生用於填充AES數據塊的字節,這樣就是要保證每個數據塊的大小是等同的(因為需要異或計算還有方面算法進行數據處理,詳細可以查看AES的算法原理)。
5. setUserAuthenticationRequired(true)調用意味著在使用key之前用戶的身份需要被認證。
每次KeyGenParameterSpec創建的時候,他都被用來初始化KeyGenerator,這個對象會產生存儲在設備上的key。

怎麼使用CryptoObjectHelper呢?

下面我們看一下怎麼使用CryptoObjectHelper這個類,我們直接看代碼就知道了:

CryptoObjectHelper cryptoObjectHelper = new CryptoObjectHelper();
fingerprintManager.authenticate(cryptoObjectHelper.buildCryptoObject(), 0,
       cancellationSignal, myAuthCallback, null);

使用是比較簡單的,首先new一個CryptoObjectHelper對象,然後調用buildCryptoObject方法就能得到CryptoObject對象了。

處理用戶的指紋認證結果

前面我們分析authenticate接口的時候說道,調用這個接口的時候必須提供FingerprintManager.AuthenticationCallback類的對象,這個對象會在指紋認證結束之後系統回調以通知app認證的結果的。在android 6.0中,指紋的掃描和認證都是在另外一個進程中完成(指紋系統服務)的,因此底層什麼時候能夠完成認證我們app是不能假設的。因此,我們只能采取異步的操作方式,也就是當系統底層完成的時候主動通知我們,通知的方式就是通過回調我們自己實現的FingerprintManager.AuthenticationCallback類,這個類中定義了一些回調方法以供我們進行必要的處理:

下面我們簡要介紹一下這些接口的含義:
1. OnAuthenticationError(int errorCode, ICharSequence errString) 這個接口會再系統指紋認證出現不可恢復的錯誤的時候才會調用,並且參數errorCode就給出了錯誤碼,標識了錯誤的原因。這個時候app能做的只能是提示用戶重新嘗試一遍。
2. OnAuthenticationFailed() 這個接口會在系統指紋認證失敗的情況的下才會回調。注意這裡的認證失敗和上面的認證錯誤是不一樣的,雖然結果都是不能認證。認證失敗是指所有的信息都采集完整,並且沒有任何異常,但是這個指紋和之前注冊的指紋是不相符的;但是認證錯誤是指在采集或者認證的過程中出現了錯誤,比如指紋傳感器工作異常等。也就是說認證失敗是一個可以預期的正常情況,而認證錯誤是不可預期的異常情況。
3. OnAuthenticationHelp(int helpMsgId, ICharSequence helpString) 上面的認證失敗是認證過程中的一個異常情況,我們說那種情況是因為出現了不可恢復的錯誤,而我們這裡的OnAuthenticationHelp方法是出現了可以回復的異常才會調用的。什麼是可以恢復的異常呢?一個常見的例子就是:手指移動太快,當我們把手指放到傳感器上的時候,如果我們很快地將手指移走的話,那麼指紋傳感器可能只采集了部分的信息,因此認證會失敗。但是這個錯誤是可以恢復的,因此只要提示用戶再次按下指紋,並且不要太快移走就可以解決。
4. OnAuthenticationSucceeded(FingerprintManagerCompati.AuthenticationResult result)這個接口會在認證成功之後回調。我們可以在這個方法中提示用戶認證成功。這裡需要說明一下,如果我們上面在調用authenticate的時候,我們的CryptoObject不是null的話,那麼我們在這個方法中可以通過AuthenticationResult來獲得Cypher對象然後調用它的doFinal方法。doFinal方法會檢查結果是不是會攔截或者篡改過,如果是的話會拋出一個異常。當我們發現這些異常的時候都應該將認證當做是失敗來來處理,為了安全建議大家都這麼做。

關於上面的接口還有2點需要補充一下:
1. 上面我們說道OnAuthenticationError 和 OnAuthenticationHelp方法中會有錯誤或者幫助碼以提示為什麼認證不成功。Android系統定義了幾個錯誤和幫助碼在FingerprintManager類中,如下:

我們的callback類實現的時候最好需要處理這些錯誤和幫助碼。

2. 當指紋掃描器正在工作的時候,如果我們取消本次操作的話,系統也會回調OnAuthenticationError方法的,只是這個時候的錯誤碼是FingerprintManager.FINGERPRINT_ERROR_CANCELED(值為5),因此app需要區別對待。
下面給出我的代碼中實現的callback子類:

package com.createchance.fingerprintdemo;

import android.os.Handler;
import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;

/**
 * Created by baniel on 7/21/16.
 */
public class MyAuthCallback extends FingerprintManagerCompat.AuthenticationCallback {

 private Handler handler = null;

 public MyAuthCallback(Handler handler) {
  super();

  this.handler = handler;
 }

 @Override
 public void onAuthenticationError(int errMsgId, CharSequence errString) {
  super.onAuthenticationError(errMsgId, errString);

  if (handler != null) {
   handler.obtainMessage(MainActivity.MSG_AUTH_ERROR, errMsgId, 0).sendToTarget();
  }
 }

 @Override
 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
  super.onAuthenticationHelp(helpMsgId, helpString);

  if (handler != null) {
   handler.obtainMessage(MainActivity.MSG_AUTH_HELP, helpMsgId, 0).sendToTarget();
  }
 }

 @Override
 public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
  super.onAuthenticationSucceeded(result);

  try {
   result.getCryptoObject().getCipher().doFinal();

   if (handler != null) {
    handler.obtainMessage(MainActivity.MSG_AUTH_SUCCESS).sendToTarget();
   }
  } catch (IllegalBlockSizeException e) {
   e.printStackTrace();
  } catch (BadPaddingException e) {
   e.printStackTrace();
  }
 }

 @Override
 public void onAuthenticationFailed() {
  super.onAuthenticationFailed();

  if (handler != null) {
   handler.obtainMessage(MainActivity.MSG_AUTH_FAILED).sendToTarget();
  }
 }
}

這個子類實現很簡單,主要的實現方式就是將消息拋給主界面的Handler來處理:

handler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  super.handleMessage(msg);

  Log.d(TAG, "msg: " + msg.what + " ,arg1: " + msg.arg1);
  switch (msg.what) {
   case MSG_AUTH_SUCCESS:
    setResultInfo(R.string.fingerprint_success);
    mCancelBtn.setEnabled(false);
    mStartBtn.setEnabled(true);
    cancellationSignal = null;
    break;
   case MSG_AUTH_FAILED:
    setResultInfo(R.string.fingerprint_not_recognized);
    mCancelBtn.setEnabled(false);
    mStartBtn.setEnabled(true);
    cancellationSignal = null;
    break;
   case MSG_AUTH_ERROR:
    handleErrorCode(msg.arg1);
    break;
   case MSG_AUTH_HELP:
    handleHelpCode(msg.arg1);
    break;
  }
 }
};

這裡分別處理四中回調,並且針對錯誤碼調用handleErrorCode方法處理:

private void handleErrorCode(int code) {
 switch (code) {
  case FingerprintManager.FINGERPRINT_ERROR_CANCELED:
   setResultInfo(R.string.ErrorCanceled_warning);
   break;
  case FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE:
   setResultInfo(R.string.ErrorHwUnavailable_warning);
   break;
  case FingerprintManager.FINGERPRINT_ERROR_LOCKOUT:
   setResultInfo(R.string.ErrorLockout_warning);
   break;
  case FingerprintManager.FINGERPRINT_ERROR_NO_SPACE:
   setResultInfo(R.string.ErrorNoSpace_warning);
   break;
  case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
   setResultInfo(R.string.ErrorTimeout_warning);
   break;
  case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
   setResultInfo(R.string.ErrorUnableToProcess_warning);
   break;
 }
}

很簡單,就是針對不同的錯誤碼,設置界面上不同的顯示文字,以提示用戶。這裡大家可以很據自己的需要修改邏輯。
針對幫助碼調用handleHelpCode方法處理:

private void handleHelpCode(int code) {
 switch (code) {
  case FingerprintManager.FINGERPRINT_ACQUIRED_GOOD:
   setResultInfo(R.string.AcquiredGood_warning);
   break;
  case FingerprintManager.FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
   setResultInfo(R.string.AcquiredImageDirty_warning);
   break;
  case FingerprintManager.FINGERPRINT_ACQUIRED_INSUFFICIENT:
   setResultInfo(R.string.AcquiredInsufficient_warning);
   break;
  case FingerprintManager.FINGERPRINT_ACQUIRED_PARTIAL:
   setResultInfo(R.string.AcquiredPartial_warning);
   break;
  case FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST:
   setResultInfo(R.string.AcquiredTooFast_warning);
   break;
  case FingerprintManager.FINGERPRINT_ACQUIRED_TOO_SLOW:
   setResultInfo(R.string.AcquiredToSlow_warning);
   break;
 }
}

這裡的處理和handleErrorCode是一樣的。

總結

這裡我們總計一下,android 6.0上的指紋識別開發的幾個要點:
1. 建議使用Android Support Library v4 Compatibility API,不要使用直接framework中的api。
2. 在使用指紋硬件之前一定要檢查上面提到的幾個檢查條件
3. 根據google的建議最好使用google提供的指紋是被icon來標示你的指紋識別界面:

這個做的目的就是為了很明確地提示用戶這是一個指紋識別操作,就像人們看到藍牙的那個小標識就知道這是藍牙操作一樣。當然,這只是google的一個實踐性的建議,並非強制。
4. app需要及時通知用戶當前的操作以及操作的結果,比如需要明確告訴用戶當前正在掃描指紋,請把你的指紋放在傳感器上等。
5. 最後需要注意的就是Android Support Library v4中的FingerprintManager類名字是FingerprintManagerCompat,並且他們的authenticate方法參數順序不一樣,flags和cancel的位置在兩個類中是不一樣的,這一點需要注意(個人覺得,這會不會是google的失誤呢???嘿嘿。。。。。)

demo運行效果截圖(運行於nexus 5x)

初始狀態

這裡寫圖片描述 

掃描狀態

這裡寫圖片描述 

掃描失敗(出現可以恢復的錯誤,這裡是手指移動太快)

這裡寫圖片描述 

認證失敗

這裡寫圖片描述 

認證成功

這裡寫圖片描述

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved