Android M指紋的資料太少,經過一段時間閱讀原生Android代碼,寫了以下例子,貢獻出來給需要幫助的人。
以下內容基於64位的高通CPU,搭載fpc1020芯片,此部分代碼在原生android上做了更改,以應付工廠指紋的測試。原生android指紋錄入需要采集10次(因不同的芯片而定)。
代碼簡單說明:
1. FingerPrintEnrollBase類:
重要的是
Java代碼
- 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指紋的采集流程圖:
源碼如下:
FingerPrintEnrollBase:
Java代碼
- /*
- * 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:
Java代碼
- 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;
- }
- }
- }
-
- }