English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
There is too little information about Android M fingerprint, after reading the native Android code for a period of time, the following examples were written, contributed to those in need of help.
The following content is based on64high-performance Qualcomm CPU, equipped with fpc1020 chip, this part of the code has been changed on the native android to deal with the factory fingerprint test. Native android fingerprint enrollment requires collecting10times (due to different chips).
Code simple explanation:
1. FingerPrintEnrollBase class:
What is important is
Java code
public interface Listener { void onEnrollmentHelp(CharSequence helpString); void onEnrollmentError(int errMsgId, CharSequence errString); void onEnrollmentProgressChange(int steps, int remaining); }
This interface.
1The onEnrollmentHelp function: is the fingerprint operation help information returned by the lower layer.
2The onEnrollmentError function is the error information returned by the lower layer, errMsgId is the type of error information, among which1Indicates that the fingerprint hardware is unavailable.3Indicates timeout.5Operation has been canceled. errString is the text information corresponding to errMsgId, and it is for those who need to experiment themselves.
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上),这将直接导致程序崩溃!
fpc指纹采集流程图:
源码如下:
FingerPrintEnrollBase:
Java code
/* * 版权(C) 2015 Android开源项目 * * 根据Apache许可证版本 20("许可证"); * 您只能在遵守许可证的情况下使用此文件。 * 您可以在以下位置获取许可证副本: * * http://www.apache.org/许可/许可证-20 * * 除非适用法律要求或书面同意,否则软件 * 根据许可证分发的软件是在“按原样”的基础上分发的, * 不提供任何形式(明示或暗示)的保证或条件。 * 查看许可证以了解具体语言规范权限和 * 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 code
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")63;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; } } } }
This is the organization of Android fingerprint information, and we will continue to supplement relevant information. Thank you for your support to our site!