Application Scenarios

A wide range of apps, notably those related to e-commerce, require account sign-in. Due to this reality, both you and your app's users are concerned with the security in the current cyberspace.

HUAWEI Account Kit equips apps with simple and secure sign-in and authentication functions, providing for unmatched peace of mind. Rather than repeatedly entering a dedicated account name and password, and then waiting to be authenticated, the user can simply tap on the Sign in with HUAWEI ID button, to enjoy direct access to your app via a HUAWEI ID.
Safety Detect offers a range of different APIs to perform security checks. For example, the UserDetect API can help your app avoid such behaviors as batch registrations, credential stuffing attacks, promotional bonus hunting, and content crawling.
FIDO offers local biometric authentication and online identity verification. Apps bolstered by FIDO allow users to sign in by fingerprint or facial recognition, delivering airtight security alongside greater convenience.

What You Will Create

In this codelab, you will use the demo projects to call APIs of Account Kit, Safety Detect, and FIDO BioAuthn. Through the demo projects, you will:

What You Will Learn

In this codelab, you will learn how to:

What You Will Need

Hardware Requirements

Software Requirements

To integrate the kits, you'll need to complete the following preparations:

For more details, please refer to Preparations for Integrating HUAWEI HMS Core.

The following are the methods that can be used to enable the kits.
Method 1 is for Account Kit; methods 2 and 3 are for Safety Detect and FIDO.

Method 1

Sign in to AppGallery Connect and click My projects. In the project list, select the created app. Then in Project settings, click Manage APIs.

Toggle on the switches for Account Kit, Safety Detect, and FIDO.

Method 2

Sign in to AppGallery Connect. Go to HMS API Services > API Library and select the API you wish to enable.

Enabling Safety Detect

Click Safety Detect on the API Library page.

On the displayed page, click Enable to enable Safety Detect.

If the kit is enabled, the page will display as shown below:

Enabling FIDO

On the API Library page, click FIDO.

On the page displayed, click Enable to enable FIDO.

If the kit is enabled, the page will display as shown below:

Obtaining the Configuration File

Sign in to AppGallery Connect and click My projects. Find your app project and click the app that needs to integrate the HMS Core SDK. Go to Project settings > General information. Then in the Project area, click Set.

Set the app data storage location, and click OK.

In the App information area, download the agconnect-services.json file.

Move the downloaded agconnect-services.json file to the root directory of the app directory in your Android Studio project.

Configuring Dependencies for HMS Core SDKs

Open the build.gradle file in the app directory.

Add dependencies for the Account SDK, Safety Detect SDK, and FIDO BioAuthn SDK to dependencies.

dependencies { // HMS Core - Account Kit implementation 'com.huawei.hms:hwid:{version}' // HMS Core - Safety Detect implementation 'com.huawei.hms:safetydetect:{version}' // HMS Core - FIDO BioAuthn implementation 'com.huawei.hms:fido-bioauthn-androidx:{version}' }

Click Sync Now to synchronize your project.

Configuring Obfuscation Scripts

  1. Open the obfuscation script file proguard-rules.pro for your Android Studio project.
  2. Add configurations to exclude the SDK from obfuscation.
    -ignorewarnings -keepattributes *Annotation* -keepattributes Exceptions -keepattributes InnerClasses -keepattributes Signature -keepattributes SourceFile,LineNumberTable -keep class com.huawei.hianalytics.**{*;} -keep class com.huawei.updatesdk.**{*;} -keep class com.huawei.hms.**{*;}
  3. If you are using AndResGuard, add its trustlist to the obfuscation configuration file.
    "R.string.hms*", "R.string.connect_server_fail_prompt_toast", "R.string.getting_message_fail_prompt_toast", "R.string.no_available_network_prompt_toast", "R.string.third_app_*", "R.string.upsdk_*", "R.layout.hms*", "R.layout.upsdk_*", "R.drawable.upsdk*", "R.color.upsdk*", "R.dimen.upsdk*", "R.style.upsdk*", "R.string.agc*"

Overview

You can call the UserDetect API of Safety Detect for fake user detection by following the steps below:

Step 1 Initialize Safety Detect.

Step 2 Initiate a detection request: Call the userDetection() method of the UserDetect API to initiate a fake user detection request. The API will return a response token.

Step 3 Obtain the detection result: Use the response token to call an API to obtain the detection result.

—End

Initializing Safety Detect

You can initialize Safety Detect on the sign-in page of the app.

The UserDetect API provides the behavior detection capability. To use the capability, you can call the initUserDetect() method to initialize fake user detection. The sample code is as follows:

Java code

/** * init safety detect */ private void initSafetyDetect() { // init SafetyDetect SafetyDetectClient client = SafetyDetect.getClient(this); client.initUserDetect().addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { // init success } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // init fail } }); }

Kotlin code

/** * init safety detect */ private fun initSafetyDetect() { // init SafetyDetect val client = SafetyDetect.getClient(this) client.initUserDetect().addOnSuccessListener { // init success }.addOnFailureListener { // init fail } }

Initiating a Detection Request

After the user taps on the sign-in button, the app calls userDetection to initiate a fake user detection, and inputs the app_id that you have applied for as the parameter of the method.

Add OnSuccessListener and OnFailureListener as listeners.

Java code

String app_Id = AGConnectServicesConfig.fromContext(this).getString("client/app_id"); SafetyDetectClient client = SafetyDetect.getClient(this); client.userDetection(app_Id).addOnSuccessListener(new OnSuccessListener<UserDetectResponse>() { @Override public void onSuccess(UserDetectResponse userDetectResponse) { // String responseToken = userDetectResponse.getResponseToken(); // if (!responseToken.isEmpty()) { // Send the response token to your app server, and call the cloud API of // HMS Core on your server to obtain the fake user detection result. // } } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Log.e(TAG, "user detect fail"); } });

Kotlin code

val appId = AGConnectServicesConfig.fromContext(this).getString("client/app_id") val client = SafetyDetect.getClient(this) client.userDetection(appId).addOnSuccessListener { // String responseToken = userDetectResponse.getResponseToken(); // if (!responseToken.isEmpty()) { // Send the response token to your app server, and call the cloud API of // HMS Core on your server to obtain the fake user detection result. // } }.addOnFailureListener { Log.e(TAG, "user detect fail") }

After calling userDetection, the app pops up a dialog for fake user detection. The figure below is an example.

Obtaining the Detection Result

Call an on-cloud API (nocaptcha in the Chinese mainland and verify outside the Chinese mainland) based on the response token obtained in the previous step, to obtain the user detection result.

To obtain the detection result, perform the following steps on the server:

Step 1 Obtain the access token. For more details, please refer to OAuth 2.0-based Authentication.

Step 2 Call the on-cloud API to obtain the detection result.

The following is an example of a request:

POST https://hirms.cloud.huawei.com/rms/v1/userRisks/verify?appId=123456 HTTP/1.1 Content-Type: application/json;charset=utf-8
{ "accessToken":"AAWWHI94sgUR2RU5_P1ZptUiwLq7W8XWJO2LxaAPuXw4_HOJFXnBlN-q5_3bwlxVW_SHeDPx_s5bWW-9DjtWZsvcm9CwXe1FHJg0u-D2pcQPcb3sTxDTJeiwEb9WBPl_9w", "response":"1_55d74c04eab36a0a018bb7a879a6f49f072b023690cba936" }

—End

Add the Sign In with HUAWEI ID button to the sign-in page of the app.

<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton android:id="@+id/login_huaweiAccount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_gravity="center_horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/login_otherLogin" app:layout_constraintVertical_bias="0.2" tools:ignore="MissingConstraints" />

The sign-in page is shown as below:

The sample code for adding the Sign In with HUAWEI ID button to the sign-in page is as follows:
Java code

/** * HUAWEI Account Login in */ private void onHuaweiAccountLogin() { AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM) .setIdToken().createParams(); AccountAuthService mAuthService = AccountAuthManager.getService(this, authParams); startActivityForResult(mAuthService.getSignInIntent(), REQUEST_CODE); }

Kotlin code

/** * HUAWEI Account Login in */ private fun onHuaweiAccountLogin() { val authParams: AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM) .setIdToken().createParams() val mAuthService: AccountAuthService = AccountAuthManager.getService(this, authParams) startActivityForResult(mAuthService.signInIntent, REQUEST_CODE) }

HUAWEI ID sign-in authentication:

After a successful authentication, the app processes the following code:
Java code

@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE) { Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data); if (authAccountTask.isSuccessful()) { //login success AuthAccount authAccount = authAccountTask.getResult(); onHuaweiIdLoginSuccess(authAccount); } else { Log.e(TAG, "sign in failed : " + ((ApiException) authAccountTask.getException()).getStatusCode()); } } }

Kotlin code

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE) { val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data) if (authAccountTask.isSuccessful) { //login success val authAccount = authAccountTask.result onHuaweiIdLoginSuccess(authAccount) } else { Log.e(TAG, "sign in failed : " + (authAccountTask.exception as ApiException).statusCode) } } }

After a successful sign-in, the app processes the following code to handle the HUAWEI ID information.

Java code

/** * HUAWEI Account Login success */ private void onHuaweiIdLoginSuccess(AuthAccount authAccount) { String openId = authAccount.getOpenId(); Log.i(TAG, "OpenId : " + openId); SPUtil.put(this, SPConstants.KEY_OPENID, openId); // save user info UserBean userBean = UserUtil.getLocalUser(this, openId); if (userBean == null) { userBean = new UserBean(); userBean.setAvatar(authAccount.getAvatarUriString()); userBean.setDisplayName(authAccount.getDisplayName()); String localStr = new Gson().toJson(userBean); SPUtil.put(this, openId, localStr); } startActivity(new Intent(this, HomeAct.class)); finish(); }

Kotlin code

/** * HUAWEI Account Login success */ private fun onHuaweiIdLoginSuccess(authAccount: AuthAccount) { val openId = authAccount.openId Log.i(TAG, "OpenId : $openId") // is login SPUtil.put(this, SPConstants.KEY_OPENID, openId) var userBean: UserBean? = UserUtil.getLocalUser(this, openId) if (userBean == null) { userBean = UserBean(authAccount.displayName, authAccount.avatarUriString) val localStr = Gson().toJson(userBean) SPUtil.put(this, openId, localStr) } startActivity(Intent(this, HomeAct::class.java)) finish() }

After a successful sign-in, the user information will display, as shown below:

The fingerprint authentication capability enables the app to facilitate fingerprint sign-in. The process is as follows:

  1. A user attempts to sign in to the app.
  2. The app checks whether the current device supports the fingerprint sign-in function.
  3. If the device supports the function, the app enables the function and saves the OpenID of the HUAWEI ID used for sign-in.
  4. The user signs in to the app with his/her fingerprint. The app obtains the OpenID by decrypting the fingerprint data, and gains the user information with the OpenID.

Process

1. Signing In

A user uses a HUAWEI ID to sign in to the app. The app stores the user information with the OpenID of the HUAWEI ID.

2. Checking for Fingerprint Sign-in Support

The app checks whether the current device supports the fingerprint sign-in function. If so, it goes to the next step. The code below is used for the check:
Java code

// check fingerprint is support BioAuthnManager bioAuthnManager = new BioAuthnManager(this); int errorCode = bioAuthnManager.canAuth(); if (errorCode != 0) { // not support SPUtil.put(HomeAct.this, SPConstants.FINGER_PRINT_LOGIN_SWITCH, true); return; }

Kotlin code

// check fingerprint is support val bioAuthnManager = BioAuthnManager(this@HomeAct) val errorCode = bioAuthnManager.canAuth() if (errorCode != 0) { // not support return }

3. Enabling Fingerprint Sign-In

Step 1 Add a control for fingerprint authentication and sign-in.

Add a SwitchCompat control for enabling or disabling the fingerprint sign-in function to the app home page. By default, the function is disabled.

<androidx.appcompat.widget.SwitchCompat android:id="@+id/setting_fingerprint" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/dimen_10" android:checked="false" android:thumb="@drawable/switch_circle_bg" app:track="@drawable/switch_bg" />

Add an event listener to the SwitchCompat control.

Java code

mSwitchCompat.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSwitchCompat.isChecked()) { // open fingerprint onFingerprintOpenCheck(); } else { // close fingerprint onFingerprintCloseCheck(); } } });

Kotlin code

home_fingerprint.setOnClickListener { if (home_fingerprint.isChecked) { // open fingerprint onFingerprintOpenCheck(); } else { // close fingerprint onFingerprintCloseCheck(); } }

Step 2 Generate an encrypting cipher.

The app generates a cipher according to the encrypted key that has generated in either symmetric or asymmetric encryption mode.

Java code

/** * get Encrypt Cipher */ public Cipher getEncryptCipher() { Cipher cipher = null; try { cipher = Cipher.getInstance(JAVA_TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, getKey()); } catch (Exception e) { e.printStackTrace(); } return cipher; }

Kotlin code

/** * get Encrypt Cipher */ fun getEncryptCipher(): Cipher? { var cipher: Cipher? = null try { cipher = Cipher.getInstance(KOTLIN_TRANSFORMATION) cipher.init(Cipher.ENCRYPT_MODE, getKey()) } catch (e: java.lang.Exception) { e.printStackTrace() } return cipher }

Step 3 Generate CryptoObject.

Obtain com.huawei.hms.support.api.fido.bioauthn.CryptoObject.

Java code

// get cryptoObject CryptoObject cryptoObject = new CryptoObject(KeyHelper.getInstance().getEncryptCipher()); bioAuthnPrompt.auth(info, cryptoObject);

Kotlin code

// get cryptoObject val cryptoObject = KeyHelper.getInstance().getEncryptCipher()?.let { CryptoObject(it) } if (cryptoObject != null) { bioAuthnPrompt.auth(info, cryptoObject) }

Step 4 Call the fingerprint authentication capability.

Java code

/** * open fingerprint */ private void onFingerprintOpen() { BioAuthnPrompt bioAuthnPrompt = new BioAuthnPrompt(this, ContextCompat.getMainExecutor(this), authCallback); BioAuthnPrompt.PromptInfo.Builder builder = new BioAuthnPrompt.PromptInfo.Builder() .setTitle("This is the title.") .setSubtitle("This is the subtitle") .setDescription("This is the description"); builder.setNegativeButtonText("This is the 'Cancel' button."); BioAuthnPrompt.PromptInfo info = builder.build(); // get cryptoObject CryptoObject cryptoObject = new CryptoObject(KeyHelper.getInstance().getEncryptCipher()); bioAuthnPrompt.auth(info, cryptoObject); }

Kotlin code

/** * open fingerprint */ private fun onFingerprintOpen() { val bioAuthnPrompt = BioAuthnPrompt(this, ContextCompat.getMainExecutor(this), authCallback) val builder = BioAuthnPrompt.PromptInfo.Builder() .setTitle("This is the title.") .setSubtitle("This is the subtitle") .setDescription("This is the description") builder.setNegativeButtonText("This is the 'Cancel' button.") val info = builder.build() // get cryptoObject val cryptoObject = KeyHelper.getInstance().getEncryptCipher()?.let { CryptoObject(it) } if (cryptoObject != null) { bioAuthnPrompt.auth(info, cryptoObject) } }

When the fingerprint authentication capability is successfully enabled, the app will display a dialog for fingerprint scanning. For example:

After the user scans the fingerprint, the app obtains the result through authCallback, and saves the OpenID in onAuthSucceeded(@NotNull BioAuthnResult result).

Java code

// call back BioAuthnCallback authCallback = new BioAuthnCallback() { @Override public void onAuthError(int errMsgId, @NonNull CharSequence errString) { // TODO Auth Error Log.e(TAG, "auth error : " + errString); onFingerprintOpenResult(false); } @Override public void onAuthSucceeded(@NonNull BioAuthnResult result) { // Auth Success try { CryptoObject cryptoObject = result.getCryptoObject(); if (null == cryptoObject) { Log.e(TAG, "auth success cryptoObject is null"); onFingerprintOpenResult(false); return; } Cipher cipher = result.getCryptoObject().getCipher(); if (null == cipher) { Log.e(TAG, "auth success cipher is null"); onFingerprintOpenResult(false); return; } String openId = (String) SPUtil.get(HomeAct.this, SPConstants.KEY_OPENID, ""); byte[] bytes = cipher.doFinal(openId.getBytes()); // save Encode FingerprintHelper.put(HomeAct.this, SPConstants.KEY_SAVE_ENCODE, Base64.encodeToString(bytes, Base64.URL_SAFE)); // save IV byte[] iv = cipher.getIV(); FingerprintHelper.put(HomeAct.this, SPConstants.KEY_SAVE_IV, Base64.encodeToString(iv, Base64.URL_SAFE)); Log.i(TAG, "auth success"); onFingerprintOpenResult(true); } catch (Exception e) { e.printStackTrace(); } } @Override public void onAuthFailed() { // TODO Auth Failed Log.e(TAG, "auth failed"); onFingerprintOpenResult(false); } };

Kotlin code

// call back private var authCallback: BioAuthnCallback = object : BioAuthnCallback() { override fun onAuthError(errMsgId: Int, errString: CharSequence) { // TODO Auth Error Log.e("authCallback", "auth error : $errString") onFingerprintOpenResult(false); } override fun onAuthSucceeded(result: BioAuthnResult) { // Auth Success try { val cryptoObject = result.cryptoObject if (null == cryptoObject) { Log.e("authCallback", "auth success cryptoObject is null") onFingerprintOpenResult(false); return } val cipher = result.cryptoObject!!.cipher if (null == cipher) { Log.e("authCallback", "auth success cipher is null") onFingerprintOpenResult(false); return } val openId = SPUtil[this@HomeAct, SPConstants.KEY_OPENID, ""] as String val bytes = cipher.doFinal(openId.toByteArray()) // save Encode FingerprintHelper.put(this@HomeAct, SPConstants.KEY_SAVE_ENCODE, Base64.encodeToString(bytes, Base64.URL_SAFE)) // save IV val iv = cipher.iv FingerprintHelper.put(this@HomeAct, SPConstants.KEY_SAVE_IV, Base64.encodeToString(iv, Base64.URL_SAFE)) Log.i("authCallback", "auth success") onFingerprintOpenResult(true); } catch (e: Exception) { e.printStackTrace() } } override fun onAuthFailed() { // TODO Auth Failed Log.e("authCallback", "auth failed") onFingerprintOpenResult(false); } }

4. Fingerprint Sign-In

Step 1 Add the button for fingerprint sign-in to the app sign-in page.

<androidx.appcompat.widget.AppCompatTextView android:id="@+id/login_fingerprint" android:layout_width="200dp" android:layout_height="36dp" android:layout_gravity="center_vertical" android:background="@drawable/bg_fingerprint" android:drawableStart="@drawable/fingerprint" android:drawablePadding="@dimen/dimen_8" android:gravity="center_vertical" android:paddingStart="@dimen/dimen_20" android:text="@string/fingerprint" android:textColor="@color/white" android:textSize="@dimen/text_16" android:visibility="gone" app:flow_horizontalAlign="start" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/login_huaweiAccount" app:layout_constraintStart_toStartOf="@+id/login_huaweiAccount" app:layout_constraintTop_toBottomOf="@+id/login_huaweiAccount" app:layout_constraintVertical_bias="0.1" tools:ignore="MissingConstraints,RtlSymmetry" />

Step 2 Call the fingerprint sign-in function.

The code below shows how to call this function:

Java code

/** * Fingerprint login */ private void onFingerprintLogin() { BioAuthnPrompt bioAuthnPrompt = new BioAuthnPrompt(this, ContextCompat.getMainExecutor(this), loginCallback); BioAuthnPrompt.PromptInfo.Builder builder = new BioAuthnPrompt.PromptInfo.Builder().setTitle("This is the title.") .setSubtitle("This is the subtitle") .setDescription("This is the description"); builder.setNegativeButtonText("This is the 'Cancel' button."); BioAuthnPrompt.PromptInfo info = builder.build(); // save IV String ivStr = FingerprintHelper.get(this, SPConstants.KEY_SAVE_IV); byte[] iv = Base64.decode(ivStr, Base64.URL_SAFE); CryptoObject cryptoObject = new CryptoObject(KeyHelper.getInstance().getDecryptCipher(iv)); bioAuthnPrompt.auth(info, cryptoObject); }

Kotlin code

/** * Fingerprint login */ private fun onFingerprintLogin() { val bioAuthnPrompt = BioAuthnPrompt(this, ContextCompat.getMainExecutor(this), loginCallback) val builder = BioAuthnPrompt.PromptInfo.Builder().setTitle("This is the title.") .setSubtitle("This is the subtitle") .setDescription("This is the description") builder.setNegativeButtonText("This is the 'Cancel' button.") val info = builder.build() // save IV val ivStr = FingerprintHelper[this, SPConstants.KEY_SAVE_IV] val iv = Base64.decode(ivStr, Base64.URL_SAFE) val cryptoObject = CryptoObject(getInstance().getDecryptCipher(iv)!!) bioAuthnPrompt.auth(info, cryptoObject) }

Obtain the decrypting cipher.

Java code

/** * get decrypt cipher */ public Cipher getDecryptCipher(byte[] initializeVector) { Cipher cipher = null; try { cipher = Cipher.getInstance(JAVA_TRANSFORMATION); IvParameterSpec ivParameterSpec = new IvParameterSpec(initializeVector); cipher.init(Cipher.DECRYPT_MODE, getKey(), ivParameterSpec); } catch (Exception e) { e.printStackTrace(); } return cipher; }

Kotlin code

/** * get decrypt cipher */ fun getDecryptCipher(initializeVector: ByteArray?): Cipher? { var cipher: Cipher? = null try { cipher = Cipher.getInstance(KOTLIN_TRANSFORMATION) val ivParameterSpec = IvParameterSpec(initializeVector) cipher.init(Cipher.DECRYPT_MODE, getKey(), ivParameterSpec) } catch (e: Exception) { e.printStackTrace() } return cipher }

When the API is successfully called, the app will display a dialog for fingerprint scanning. For example:

After the user scans the fingerprint, the app obtains the result through loginCallback, and obtains the OpenID in onAuthSucceeded(@NotNull BioAuthnResult result).

Java code

// call back BioAuthnCallback loginCallback = new BioAuthnCallback() { @Override public void onAuthError(int errMsgId, @NonNull CharSequence errString) { // TODO Login Auth Error Log.e("loginCallback", "login auth error : " + errString); } @Override public void onAuthSucceeded(@NonNull BioAuthnResult result) { try { CryptoObject cryptoObject = result.getCryptoObject(); if (null == cryptoObject) { Log.e(TAG, "auth success cryptoObject is null"); return; } Cipher cipher = result.getCryptoObject().getCipher(); if (null == cipher) { Log.e(TAG, "cipher is null"); return; } String saveEncode = FingerprintHelper.get(LoginAct.this, SPConstants.KEY_SAVE_ENCODE); byte[] input = Base64.decode(saveEncode, Base64.URL_SAFE); byte[] bytes = cipher.doFinal(input); String saveString = new String(bytes); Log.i(TAG, "auth success openId:" + saveString); onFingerprintLoginSuccess(saveString); } catch (Exception e) { e.printStackTrace(); } } @Override public void onAuthFailed() { // TODO Auth Failed Log.e(TAG, "auth failed"); } };

Kotlin code

// call back private var loginCallback: BioAuthnCallback = object : BioAuthnCallback() { override fun onAuthError(errMsgId: Int, errString: CharSequence) { // TODO Login Auth Error Log.e("loginCallback", "login auth error : $errString") } override fun onAuthSucceeded(result: BioAuthnResult) { try { val cryptoObject = result.cryptoObject if (null == cryptoObject) { Log.e("loginCallback", "auth success cryptoObject is null") return } val cipher = result.cryptoObject!!.cipher if (null == cipher) { Log.e(TAG, "cipher is null") return } val saveEncode = FingerprintHelper[this@LoginAct, SPConstants.KEY_SAVE_ENCODE] val input = Base64.decode(saveEncode, Base64.URL_SAFE) val bytes = cipher.doFinal(input) val saveString = String(bytes) Log.i(TAG, "auth success save openId:$saveString") onFingerprintLoginSuccess(saveString) } catch (e: Exception) { e.printStackTrace() } } override fun onAuthFailed() { // TODO Auth Failed Log.e("loginCallback", "auth failed") } }

Step 3 Sign in to the app with a fingerprint and proceed to the home page.

Java code

/** * fingerprint login success */ private void onFingerprintLoginSuccess(String openId) { SPUtil.put(this, SPConstants.KEY_OPENID, openId); startActivity(new Intent(this, HomeAct.class)); }

Kotlin code

/** * fingerprint login success */ private fun onFingerprintLoginSuccess(openId: String) { SPUtil.put(this, SPConstants.KEY_OPENID, openId) startActivity(Intent(this, HomeAct::class.java)) }

After a successful fingerprint sign-in, the user information will display, as shown below:

Well done. You have successfully completed this codelab, and learned how to:

For more information, please refer to:

The source code can be found at:

Source code

Code copied