Android6.0指纹识别开发案例

所属分类: 软件编程 / Android 阅读数: 29
收藏 0 赞 0 分享

Android M指纹的资料太少,经过一段时间阅读原生Android代码,写了以下例子,贡献出来给需要帮助的人。
以下内容基于64位的高通CPU,搭载fpc1020芯片,此部分代码在原生android上做了更改,以应付工厂指纹的测试。原生android指纹录入需要采集10次(因不同的芯片而定)。

代码简单说明:

1. FingerPrintEnrollBase类:
重要的是

public interface Listener { 
  void onEnrollmentHelp(CharSequence helpString); 
  void onEnrollmentError(int errMsgId, CharSequence errString); 
  void onEnrollmentProgressChange(int steps, int remaining); 
} 

这个接口。
  1)onEnrollmentHelp函数:是下层返回的指纹操作帮助信息。
  2)onEnrollmentError函数是下层返回的错误信息,errMsgId是错误信息类型,其中1表示指纹硬件不可用,3表示超时,5表示操作已取消。errString是errMsgId对应的文字信息,有需要的自己实验就知道了。
  3)onEnrollmentProgressChange()函数是显示当前指纹的采集情况,steps:总共需要录入多少次;remaining是剩余多少次,我在此函数中有打印Log。

2. FingerPrintActivity是主Activity类,FingerPrintEnrollBase是指纹Base类。
需要特别说明的是,在FingerPrintEnrollBase类中有一句:private byte[] mToken = new byte[69];这个数组正常情况是通过输入密码后经由framework层向hal层申请的,我这里为了省去验证那一块的代码,通过sizeof(hw_auth_token_t)计算出来的为69,需要的请依此计算。我在代码里实验过,此数组如果不是69(在64位CPU上),将直接导致程序crach!
fpc指纹的采集流程图:

/* 
 * Copyright (C) 2015 The Android Open Source Project 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License 
 */ 
 
package com.mediatek.test; 
 
import android.app.Activity; 
import android.app.Fragment; 
import android.content.Context; 
import android.hardware.fingerprint.FingerprintManager; 
import android.os.Bundle; 
import android.os.CancellationSignal; 
import android.os.Handler; 
import android.util.Log; 
/** 
 * local fragment to handle the state around fingerprint enrollment. 
 */ 
public class FingerPrintEnrollBase extends Fragment { 
 
 private int mEnrollmentSteps = -1; 
 private int mEnrollmentRemaining = 0; 
 private Listener mListener; 
 private boolean mEnrolling; 
 private CancellationSignal mEnrollmentCancel; 
 private Handler mHandler = new Handler(); 
 private byte[] mToken = new byte[69];//if byte length != sizeof(hw_auth_token_t), throws Exception 
 private boolean mDone; 
 private static final String TAG = "FingerPrintEnrollBase"; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setRetainInstance(true); 
 } 
 
 @Override 
 public void onAttach(Activity activity) { 
  super.onAttach(activity); 
 } 
 
 @Override 
 public void onStart() { 
  super.onStart(); 
  Log.d(TAG, "mToken length="+mToken.length); 
  if (!mEnrolling) { 
   FingerprintManager mFpM = (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE); 
   startEnrollment(mFpM); 
  } 
 } 
 
 @Override 
 public void onStop() { 
  super.onStop(); 
  if (!getActivity().isChangingConfigurations()) { 
   cancelEnrollment(); 
  } 
 } 
 
 protected void startEnrollment(FingerprintManager mFpM) { 
  mHandler.removeCallbacks(mTimeoutRunnable); 
  mEnrollmentSteps = -1; 
  mEnrollmentCancel = new CancellationSignal(); 
  if(mFpM != null){ 
   mFpM.enroll(mToken, mEnrollmentCancel, 0, mEnrollmentCallback); 
  } 
  mEnrolling = true; 
 } 
 
 protected void cancelEnrollment() { 
  mHandler.removeCallbacks(mTimeoutRunnable); 
  if (mEnrolling) { 
   mEnrollmentCancel.cancel(); 
   mEnrolling = false; 
   mEnrollmentSteps = -1; 
  } 
 } 
 
 public void setListener(Listener listener) { 
  mListener = listener; 
 } 
 
 public int getEnrollmentSteps() { 
  return mEnrollmentSteps; 
 } 
 
 public int getEnrollmentRemaining() { 
  return mEnrollmentRemaining; 
 } 
 
 public boolean isDone() { 
  return mDone; 
 } 
 
 private FingerprintManager.EnrollmentCallback mEnrollmentCallback 
   = new FingerprintManager.EnrollmentCallback() { 
 
  @Override 
  public void onEnrollmentProgress(int remaining) { 
   if (mEnrollmentSteps == -1) { 
    mEnrollmentSteps = remaining; 
   } 
   mEnrollmentRemaining = remaining; 
   mDone = remaining == 0; 
   if (mListener != null) { 
    mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining); 
   } 
  } 
 
  @Override 
  public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { 
   if (mListener != null) { 
    mListener.onEnrollmentHelp(helpString); 
   } 
  } 
 
  @Override 
  public void onEnrollmentError(int errMsgId, CharSequence errString) { 
   if (mListener != null) { 
    mListener.onEnrollmentError(errMsgId, errString); 
   } 
  } 
 }; 
 
 private final Runnable mTimeoutRunnable = new Runnable() { 
  @Override 
  public void run() { 
   cancelEnrollment(); 
  } 
 }; 
 
 public interface Listener { 
  void onEnrollmentHelp(CharSequence helpString); 
  void onEnrollmentError(int errMsgId, CharSequence errString); 
  void onEnrollmentProgressChange(int steps, int remaining); 
 } 
} 

 FingerPrintActivity:

package com.mediatek.test; 
 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.util.List; 
import java.util.Timer; 
import java.util.TimerTask; 
 
import android.R.color; 
import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.os.CancellationSignal; 
import android.os.Handler; 
import android.os.Message; 
import android.text.Spannable; 
import android.text.style.ForegroundColorSpan; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.ProgressBar; 
import android.widget.TableRow; 
import android.widget.TextView; 
import android.widget.Toast; 
 
import com.mediatek.test.R; 
import android.hardware.fingerprint.Fingerprint; 
import android.hardware.fingerprint.FingerprintManager; 
 
public class FingerPrintActivity extends Activity implements FingerPrintEnrollBase.Listener{ 
 private static final String TAG = "FingerPrintActivity"; 
 private MyHandler mHandler = new MyHandler(); 
 private TextView fingerPrintAcquisitionTextView, fingerPrintEnrollmentErrorView, fingerPrintEnrollmentHelpView; 
 private FingerPrintEnrollBase fpeb; 
 private FingerprintManager mFingerprintManager; 
  
 @Override 
 protected int setTitleId() { 
  return R.string.tittle_fingerprint; 
 } 
 
 @Override 
 protected Activity getActivity() { 
  return this; 
 } 
  
 @Override 
 protected void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.fingerprint); 
  fingerPrintAcquisitionTextView = (TextView)findViewById(R.id.fingerprint_message); 
  fingerPrintEnrollmentErrorView= (TextView)findViewById(R.id.fingerprint_enrollment_error); 
  fingerPrintEnrollmentHelpView= (TextView)findViewById(R.id.fingerprint_enrollment_help); 
 
  mFingerprintManager = (FingerprintManager) getActivity().getSystemService( 
    Context.FINGERPRINT_SERVICE); 
   
    
 } 
  
 private void sendMsgToHandler(int msgType, String remark){ 
  Message msg = Message.obtain(); 
  msg.what = msgType; 
  Bundle bundle = new Bundle(); 
  bundle.putString("result", remark); 
  msg.setData(bundle); 
  mHandler.sendMessage(msg); 
 } 
  
 @Override 
 public void onEnrollmentHelp(CharSequence helpString) { 
  Log.d(TAG, "==onEnrollmentHelp="+helpString.toString()); 
  sendMsgToHandler(3, helpString.toString()); 
 } 
 
 @Override 
 public void onEnrollmentError(int errMsgId, CharSequence errString) { 
  Log.d(TAG, "==onEnrollmentError errMsgId="+errMsgId+" errString="+errString.toString()); 
  if(errMsgId == 3){//time out 
   postEnrollment(); 
  }else if(errMsgId == 1){//hardware lose efficacy 
   startEnrollment(); 
  }else if(errMsgId == 5){//operation cancel 
  }else{ 
   sendMsgToHandler(4, errString.toString()); 
  } 
 } 
 
 @Override 
 public void onEnrollmentProgressChange(int steps, int remaining) { 
  Log.d(TAG, "===============onEnrollmentProgressChange======="); 
  Log.d(TAG, "steps" + steps + "||remaining=" + remaining); 
  fingerPrintEnrollmentHelpView.setText(""); 
  fingerPrintEnrollmentErrorView.setText(""); 
  sendMsgToHandler(2, getString(R.string.fingerprint_validate_success)); 
  buttonS.setEnabled(true); 
  stopFingerprint(); 
 } 
  
 private void startEnrollment(){ 
  if (fpeb == null) { 
   fpeb = new FingerPrintEnrollBase(); 
  } 
  fpeb.setListener(this); 
  fpeb.startEnrollment(mFingerprintManager); 
 } 
 private void postEnrollment(){ 
  if(mFingerprintManager != null){ 
   mFingerprintManager.postEnroll(); 
  } 
 } 
  
 private void stopFingerprint() { 
  if (fpeb != null){ 
   fpeb.cancelEnrollment(); 
   onStop(); 
  } 
 } 
  
 @Override 
 protected void onStart() { 
  super.onStart(); 
 } 
  
 @Override 
 protected void onStop() { 
  super.onStop(); 
  if(fpeb != null){ 
   fpeb.setListener(null); 
  } 
 } 
 
 @Override 
 protected void onResume() { 
  super.onResume(); 
  if(mFingerprintManager == null){ 
   mFingerprintManager = (FingerprintManager) getActivity().getSystemService( 
    Context.FINGERPRINT_SERVICE); 
  } 
   
  startEnrollment(); 
 } 
  
 @Override 
 protected void onPause() { 
  super.onPause(); 
  postEnrollment(); 
  mFingerprintManager = null; 
  stopFingerprint(); 
  fpeb = null; 
 } 
 
  
 class MyHandler extends Handler{ 
 
  @Override 
  public void handleMessage(Message msg) { 
   Bundle bundle = null; 
   super.handleMessage(msg); 
   switch (msg.what) { 
   case 0: 
    removeMessages(0); 
    bundle = msg.getData(); 
    String result = bundle.getString("result"); 
    selfTestView.setText(result); 
    selfTestView.setTextColor(result.contains("PASS")?Color.GREEN:Color.RED); 
    break; 
   case 1: 
    removeMessages(1); 
    bundle = msg.getData(); 
    String rs = bundle.getString("result"); 
    checkBroadView.setText(bundle.getString("result")); 
    checkBroadView.setTextColor(rs.contains("PASS")?Color.GREEN:Color.RED); 
    break; 
   case 2: 
    removeMessages(2); 
    bundle = msg.getData(); 
    String fingerprint = bundle.getString("result"); 
    fingerPrintAcquisitionTextView.setText(bundle.getString("result")); 
    fingerPrintAcquisitionTextView.setTextColor(fingerprint.contains("PASS")?Color.GREEN:Color.WHITE); 
    mButtonSelftest.setEnabled(true); 
    mButtonCheckerboardTest.setEnabled(true); 
    break; 
   case 3: 
    removeMessages(3); 
    bundle = msg.getData(); 
    String enrollmentHelp = bundle.getString("result"); 
    fingerPrintEnrollmentHelpView.setText(bundle.getString("result")); 
    break; 
   case 4: 
    removeMessages(4); 
    bundle = msg.getData(); 
    String enrollmentError = bundle.getString("result"); 
    fingerPrintEnrollmentErrorView.setText(bundle.getString("result")); 
    fingerPrintAcquisitionTextView.setText(""); 
    break; 
   default: 
    break; 
   } 
  } 
 } 
 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Android中加入名片扫描功能实例代码

这篇文章主要介绍了Android中加入名片扫描功能实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android仿微信发表说说实现拍照、多图上传功能

这篇文章主要为大家详细介绍了Android仿微信发表说说实现拍照、多图上传功能,使用Retrofit2.0技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

设置Android系统永不锁屏永不休眠的方法

在进行Android系统开发的时候,有些特定的情况需要设置系统永不锁屏,永不休眠。本篇文章给大家介绍Android 永不锁屏,开机不锁屏,删除设置中休眠时间选项,需要的朋友一起学习吧
收藏 0 赞 0 分享

Android Retrofit 2.0框架上传图片解决方案

这篇文章主要介绍了Android Retrofit 2.0框架上传一张与多张图片解决方案,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android自定义等待对话框

这篇文章主要为大家详细介绍了Android自定义等待对话框的实现方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android中Window添加View的底层原理

这篇文章主要介绍了Android中Window添加View的底层原理,需要的朋友可以参考下
收藏 0 赞 0 分享

Android调用系统默认浏览器访问的方法

这篇文章主要介绍了Android调用系统默认浏览器访问的方法的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android开发退出程序的方法汇总

Android程序有很多Activity,比如说主窗口A,调用了子窗口B,子窗口B又调用子窗口C,back返回子窗口B后,在B中如何关闭整个Android应用程序呢? 下面脚本之家小编就给大家介绍android开发退出程序的几种方法,感兴趣的朋友参考下吧
收藏 0 赞 0 分享

Android程序开发中单选按钮(RadioGroup)的使用详解

在android程序开发中,无论是单选按钮还是多选按钮都非常的常见,接下来通过本文给大家介绍Android程序开发中单选按钮(RadioGroup)的使用,需要的朋友参考下吧
收藏 0 赞 0 分享

Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

这篇文章主要介绍了Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多