This article starts with WeChat official account of vivo Internet technology.
Link: https://mp.weixin.qq.com/s/EHomjBy4Tvm8u962J6ZgsA
By Sun Daxiang
Google started with Android 6.0 and provided an open fingerprint identification API. This article can help developers access the basic functions of fingerprint verification, and provide the functional expansion of system application based on fingerprint verification, such as the core flow chart and key code analysis of fingerprint verification login function.
1, BasicStarting from Android 6.0, the Android system supports fingerprint recognition function, and the API of fingerprint recognition is mainly fingerprint manager.
The public methods provided by fingerprint manager are to determine whether the system supports fingerprint, whether the system has entered fingerprint, initiate fingerprint verification, cancel verification, and callback verification results.
The methods of hiding include obtaining the fingerprint list and the fingerprint id. However, after Android 9.0, Google officially does not recommend the use of the fingerprint manager interface, which is recommended
BiometricPrompt is replaced by BiometricPrompt, because the interface of BiometricPrompt cannot customize the pop-up style, and each service line has not been used uniformly. The access method of this interface will be introduced as follows:
1. Effect demonstration and demo structure introduction
1.1 fingerprint verification effect
1.2 code structure of demo
1.3 core class description
Because the fingerprint function has Android 6.0 and Android 9.0 adaptation problems, fingerprint versionm and fingerprint versionp are used to implement the encapsulation of different Android versions.
Fingermanagerwrapper, FIngerpintVersionM, and fingerversionp all implement the IFingerprintInterface interface interface through the startAuth() cancelAuth method.
Set up fingerprint verification and cancel fingerprint verification
Core class description:
Diagram of core class:
2. Access process
After access through the following six steps, the fingerprint verification function can be used normally, including whether the system supports fingerprint, whether fingerprint has been entered, pulling up fingerprint verification, canceling fingerprint verification, callback of fingerprint verification results, and adaptation to Android 6.0 and Android 9.0.
Step 1: add the following fingerprint permission function in the manifest file. See Chapter 2.1 for details
Step 2: combined judgment: whether the current system version supports fingerprint function, and the fingerprint has been entered in rom, see 2.5 and 2.6 for the judgment method
Step 3: use the FingerprintManagerWrapper object to call the startAuth method in the unified interface of IFingerprintInterface, and see Chapter 2.2 for the method of pulling up the fingerprint verification function
Step 4: FingerprintVersionM and FingerprintVersionP implement IFingerprintInterface interface respectively, and realize the fingerprint verification function of Android 6.0 and Android 9.0 respectively
Step 5: register fingerprint verification successful callback interface AuthenticationCallback in FingerprintVersionM and FingerprintVersionP respectively. See Chapter 2.3 for the implementation code
Step 6: in the activity life cycle, onStop() calls to cancel the verification interface and turn off the fingerprint verification function, as shown in Chapter 2.4
2.1 add fingerprint permission
<! -- Android 9.0 and above use fingerprint permission -- > <uses-permission android:name="android.permission.USE_BIOMETRIC"/> <! -- Android 6.0 to 8.0 and above use fingerprint permission -- > <uses-permission android:name="android.permission.USE_FINGERPRINT"/> <! -- Android 6.0 and above, get fingerprint information permission, which will be used in system application promotion chapter -- > <uses-permission android:name="android.permission.MANAGE_FINGERPRINT"/>2.2 fingerprint verification
Fingerprint version P and fingerprint version m are compatible with Android 6.0 and Android 9.0 fingerprint verification functions respectively. Fingerprint manager wrapper, fingerprint version P and fingerprint version m realize the IFingerprintInterface interface uniformly
public FingerprintManagerWrapper() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { mFingerprintImp = new FingerprintVersionP(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mFingerprintImp = new FingerprintVersionM(); } } } /** * First determine whether the system supports fingerprint, whether the system has entered fingerprint, and then call the unified fingerprint authentication method */ public void startAuth(FingerprintManagerWrapper.FingerVerifyResultListener listener) { Log.i(TAG, "------startFingerAuthenticate() enter --------"); //Determine whether fingerprint device can be used currently if (!isHardwareDetected()) { Log.e(TAG, "------hardware detected!!!--------"); return; } //Determine whether there is fingerprint at present if (!hasEnrolledFingerprints()) { Log.e(TAG, "-----has no Fingerprints!!!--------"); return; } mFingerprintImp.startAuth(listener); } /** * android6.0android9.0 Unified verification and interface cancellation */ interface IFingerprintInterface { public void startAuth(FingerprintManagerWrapper.FingerVerifyResultListener listener); public void canceAuth(); }
The Android 6.0 fingerprint verification code in fingerprint version m is as follows:
public class FingerprintVersionM implements IFingerprintInterface { @Override public void startAuth(FingerprintManagerWrapper.FingerVerifyResultListener listener) { //Cancel fingerprint verification class CancellationSignal mCancellationSignal = new CancellationSignal(); MyAuthenticationCallback authenticationCallback = new MyAuthenticationCallback(); /** * Parameter Description: * CryptoObject - CryptoObject can be added if necessary * CancellationSignal - Used to cancel fingerprint verification. If you want to cancel the verification manually, call the cancel method of this parameter * int - Meaningless, default 0 * AuthenticationCallback - Callback validation results, success, failure, etc * Handler - Passing null creates a Handler on the main thread by default to deliver messages */ mFingerprintManager.authenticate(null, mCancellationSignal, 0, authenticationCallback, null); //Call identification interface } }
The Android 9.0 fingerprint verification code in fingerprint version P is as follows:
public class FingerprintVersionP implements IFingerprintInterface { @Override public void startAuth(FingerprintManagerWrapper.FingerVerifyResultListener listener) { //Used to cancel fingerprint verification CancellationSignal mCancellationSignal = new CancellationSignal(); //Callback validation results, success, failure, etc AuthenticationCallback mAuthenticationCallback = new BiometricPrompt.AuthenticationCallback(){} //Start validation mBiometricPrompt.authenticate(mCancellationSignal, mContext.getMainExecutor(), mAuthenticationCallback); } }
2.3 fingerprint verification callback
// Fingerprint verification failure callback method onAuthenticationFailed() //The callback method for fingerprint verification success. With system permission, you can obtain fingerprint information, fingerprint name, fingerprint id, etc. through AuthenticationResult onAuthenticationSucceeded(AuthenticationResult result) //Fingerprint verification failed callback, helpMsgId=1006,helpString=6 fingers removed too fast onAuthenticationHelp(int helpMsgId, CharSequence helpString) //Fingerprints are actively turned off after multiple attempts. errMsgId=5,errString = fingerprint operation cancelled. onAuthenticationError(int errMsgId, CharSequence errString)
// The following uses of android9.0 android.hardware.fingerprint.FingerprintManager.AuthenticationCallback //android 9.0 and above android.hardware.biometrics.BiometricPrompt.AuthenticationCallback private class MyAuthenticationCallback extends AuthenticationCallback { @Override public void onAuthenticationFailed() { //Fingerprint verification failure callback method } @Override public void onAuthenticationSucceeded(AuthenticationResult result) { //The callback method for fingerprint verification success. With system permission, you can obtain fingerprint information, fingerprint name, fingerprint id, etc. through AuthenticationResult } @Override public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { //Fingerprint verification failed callback, helpMsgId=1006,helpString=6 fingers removed too fast } @Override public void onAuthenticationError(int errMsgId, CharSequence errString) { //Fingerprints are actively turned off after multiple attempts. errMsgId=5,errString = fingerprint operation cancelled. } }
2.4 cancel fingerprint verification
Cancel fingerprint verification in onStop method of activity
// After the fingerprint pop-up box home key under the screen is completely covered by other pages, it needs to be closed and pulled up again @Override protected void onStop() { super.onStop(); //In the above call fingerprint verification method, the passed cancelationsignal object mCancellationSignal.cancel(); }
2.5 judge whether the current system supports fingerprint
Although fingerprint manager is not recommended after Android 9.0, all Google system versions support fingerprint manager, and 9.0 and above do not provide an API for judging whether fingerprint function is supported
/** * Determine whether the current fingerprint function is available * * @return */ public boolean isHardwareDetected() { boolean isHardwareSupport = false; try { if (mFingerprintManager != null) { isHardwareSupport = mFingerprintManager.isHardwareDetected(); } } catch (Exception e) { Log.e(TAG, "isHardwareDetected err ", e); } Log.e(TAG, "isHardwareDetected(), isHardwareSupport= " + isHardwareSupport); return isHardwareSupport; }
2.6 judge whether the system has entered fingerprint
As above, use fingerprint manager to judge whether the system has entered fingerprint
/** * Determine whether fingerprint has been entered * * @return */ public boolean hasEnrolledFingerprints() { boolean hasEnrolledFinger = false; try { if (mFingerprintManager != null) { hasEnrolledFinger = mFingerprintManager.hasEnrolledFingerprints(); } } catch (Exception e) { Log.e(TAG, "hasEnrolledFingerprints err ", e); } Log.e(TAG, "hasEnrolledFingerprints(), hasEnrolledFinger= " + hasEnrolledFinger); return hasEnrolledFinger; }
The above basic part introduces the public API provided by Google, which basically meets the fingerprint verification function.
The following describes how to obtain fingerprint id and fingerprint list, which can meet other business needs, such as account login, payment and other functions.
2, System application promotion1. Get fingerprint id
After the fingerprint verification is successful, according to the FingerprintManager.AuthenticationResult Object can obtain fingerprint id (fingerprint id is a hidden attribute) through reflection method, and need to add permission
android.permission.MANAGE_ There are differences between Fingerprint objects in fixerprint, Android 6.0 and Android 9.0:
In Android 6.0, Fingerprint contains the attribute mFingerprintId with Fingerprint id and the public method getfingerprint id
The Fingerprint class in Android 9.0 inherits Bi ometricAuthenticator.Identifer , and the Fingerprint id is also put in this class. The property is called mBiometricId, and the method is getbiomedicid
(Android 9.0 related class dependency)
(Android 6.0 class diagram dependency)
Therefore, the method of obtaining Fingerprint object and Fingerprint id by reflection needs to adapt to Android 6.0 and Android 9.0. The detailed method is as follows:
In Android 6.0, the AuthenticationResult reflection gets the Fingerprint object, and the Fingerprint object getFingerId gets the Fingerprint id
The Fingerprint information above Android 9.0 is placed in the parent class of Fingerprint, so you need to pass the clzz.getSuperclass() get the parent object, and get the Fingerprint id in the reflection method getBiometricId
private static int getFingerId(AuthenticationResult result) { int fingerId = -1; try { Field field = result.getClass().getDeclaredField("mFingerprint"); field.setAccessible(true); Object fingerPrint = field.get(result); Class<?> clzz = Class.forName("android.hardware.fingerprint.Fingerprint"); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { Log.i(TAG, "-------ANDROID Q-------"); Class<?> supClass = clzz.getSuperclass(); Method getBiometricId = supClass.getDeclaredMethod("getBiometricId"); fingerId = (int) getBiometricId.invoke(fingerPrint); } else { Log.i(TAG, "------- ANDROID M-P-------"); Method getFingerId = clzz.getDeclaredMethod("getFingerId"); fingerId = (int) getFingerId.invoke(fingerPrint); } Log.d(TAG, "fingerId=" + fingerId); } catch (Exception e) { Log.e(TAG, "", e); } return fingerId; }
2. Get the fingerprint list in the system
The system records the fingerprint, and can obtain the fingerprint information in the fingerprint list through the reflection method
Obtain the fingerprint list json string after reflection:
android6.0: [{"mDeviceId":0,"mFingerId":1147763748,"mGroupId":0,"mName":"Fingerprint 1"},{"mDeviceId":0,"mFingerId":412764029,"mGroupId":0,"mName":"Fingerprint 2"}] android9.0: [{"mGroupId":0,"mBiometricId":-714471355,"mDeviceId":517254275456,"mName":"Fingerprint 1"},{"mGroupId":0,"mBiometricId":-803114291,"mDeviceId":517254275456,"mName":"Fingerprint 2"}]
The detailed reflection code is as follows:
1: List of fingerprints to be reflected json String, using gson Convert to AccountFingerprint Object (compatible android6.0-android10.0) Gson gson = new Gson(); Object object = getEnrolledFingerprints(mFingerprintManager); String fingerListString = gson.toJson(object) // Android 6.0-android 9.0 [{"mdeviceid": 0, "mfingerid": 1147763748, "mgroupid": 0, "mname": "fingerprint 1"},{"mDeviceId":0,"mFingerId":412764029,"mGroupId":0,"mName": "fingerprint 2"}] // Android 10.0 [{"mgroupid": 0, "mbiomitricid": - 714471355, "mdeviceid": 5172542754456, "mname": "fingerprint 1"}, {"mgroupid": 0, "mbiomitricid": - 803114291, "mdeviceid": 517254275456, "mname": "fingerprint 2"}] List<AccountFingerprint> list = gson.fromJson(fingerListString, new TypeToken<List<AccountFingerprint>>() {}.getType()); 2: reflex FingerprintManager call getEnrolledFingerprints Method to obtain the entered fingerprint list /** * Reflect to get a list of all fingerprint information of the current user * * @param fm FingerprintManagerWrapper * @return Fingerprint information list */ public static Object getEnrolledFingerprints(FingerprintManager fm) { try { if (fm != null) { Object obj = invokeMethod(fm, "getEnrolledFingerprints"); return obj; } } catch (Exception e) { VLog.e(TAG, "getEnrolledFingerprints()", e); } return null; } 3: Customized AccountFingerprint bean,compatible android6-android10 //Fingerprint bean created public class AccountFingerprint { @SerializedName("mBiometricId") private int mBiometricId; @SerializedName("mFingerId") private int mFingerId; @SerializedName("mGroupId") private int mGroupId; @SerializedName("mDeviceId") private long mDeviceId; @SerializedName("mName") private String mPrintName; }
3. Introduction to fingerprint authentication practical scenario (fingerprint login account function)
Take chestnut for example: fingerprint login function can be realized after obtaining fingerprint id and fingerprint list
- First, obtain the fingerprint list of the device and synchronize it with the server to record the account number, device, fingerprint list and binding relationship
- User uses id + account + device of fingerprint authentication to initiate login request
- The server checks the current account number, fingerprint id, device, and whether there are synchronous storage records, and returns the verification results
Fingerprint login effect
Fingerprint login interaction sequence diagram
More content, please pay attention to vivo Internet technology WeChat official account.
Note: please contact Labs2020 for reprint.