Minimum Android version:4.4 (API Level:19)
Compilation Android SDK version:API Level:34
Additional dependent third-party libraries: None
Supported CPU architectures:armeabi-v7a
,arm64-v8a
SDK package size: 4MB+
Capture image size: default capture image resolution 600px*600px
, size is about 300KB
, support custom image size range: 300px~1000px
Supported languages:
Use-permissions:
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
Starting from August 2022, the SDK supports online repository dependencies. We recommend using the online dependencies to get better convenience and flexibility.
We have fixed some potential crashes on certain Android 12 devices in version 1.3.9.5. If your current version is lower than this, we recommend upgrading to this version to address the issue.
We have addressed some issues detected by the VirusTotal platform. If your promotion relies on the detection results from this platform, please upgrade your SDK version to
Starting from version 2.0.0, we have introduced ellipse dashed guidance during the preparation stage. Additionally, we have upgraded the network security policies and updated the SDK models.
From version 3.0.0, SDK Interaction Method Changed to Near-Far Range Detection Mode,motion detection has been removed, so the properties and methods related to motion detection will not have any effect.
We recommend you read the change logs to see what has been updated in the new version of the SDK.
Install CV-Demo.apk to your phone and log in with the test account.
If you want to quickly integrate the SDK and you don't have any customization requirements for the UI part, you can follow the steps below for the dependency:
Add the repository
xxxxxxxxxx
maven { url 'https://public-n3.advai.net/repository/maven-releases/' }
Add the dependencies in your project's gradle:
xxxxxxxxxx
implementation 'ai.advance.mobile-sdk.android:liveness-detection-ui:3.4.1'
implementation 'ai.advance.mobile-sdk.android:liveness-detection:3.4.1'
The liveness UI module is delivered to you in the form of source code, and you can adjust this part of the code based on your project architecture. Please make sure to understand the UI module code before making any modifications, to avoid abnormal program execution.
Due to the incompatibility between the androidx
and support
libraries, we provide source code for both library versions:
If you are unable to successfully pull the online aar from our repository, you can click the links below to download the aar files and manually add them to the liveness
module.
You can click this link to view the version history of the SDK.
Initialization SDK.
The init method need to be called in your application class
xxxxxxxxxx
// If you have subscribed to the Global liveness service, then you need to set the last boolean value to true, otherwise please set it to false.
GuardianLivenessDetectionSDK.init(this,your market,false);
Check license
The license is obtained by your server calling our openAPI, you need to check license before starting the liveness detection activity.
xString license = "xxx";
String checkResult = GuardianLivenessDetectionSDK.setLicenseAndCheck(license);
if ("SUCCESS".equals(checkResult)) {
// license valid
startLivenessActivity();
} else {
// license is not available, expired/wrong format/appId not filed
}
The returned values of checkResult:
APPLICATION_ID_NOT_MATCH: The package name is not within the authorized scope, please check your package name.
LICENSE_EXPIRE: The license has expired, please confirm that the user has calibrated the phone time.
ERROR_LICENSE(1): The license parsing succeeded, but necessary authentication information is missing, this case generally will not occur.
ERROR_LICENSE(2): The license parsing succeeded, but the internal format is incorrect, this case also generally will not occur.
ERROR_LICENSE(3): It is highly likely that an incompatible SDK license is being used, such as using an IQA license for liveness detection.
ERROR_LICENSE(4, 5): Parsing failed, please check if the license has issues like mismatched quotes, line breaks, etc.
Set the background color of the livenessView(do not overlay a mask image on the LivenessView, if you have, please remove it)
xxxxxxxxxx
mLivenessView.setMaskColor(getResources().getColor(R.color.xxx);
Set the color of the oval frame in the livenessView:
xxxxxxxxxx
mLivenessView.setOvalColor(getResources().getColor(R.color.xxx));
Set detection timeout duration.
xxxxxxxxxx
// Settable input range: [10000,60000],unit: milliseconds,default value is 50000
GuardianLivenessDetectionSDK.set3DLivenessTimeoutMills(50000);
Capture audit images.
When this feature is enabled, we will capture multiple images during the user's movement based on your configuration.
xxxxxxxxxx
GuardianLivenessDetectionSDK.setAuditImageConfig(new AuditImageConfig
.AuditImageConfigBuilder()
.setEnableCollectSwitch(true)// The function open switch,default value is false
.setImageCaptureInterval(400)// Minimum interval time for capturing images,default interval is 400ms
.setImageMaxNumber(10)// Maximum number of captured images,default number is 10
.setImageWidth(400)// The image width,default width is 400px
.setImageQuality(30)// The image compress quality,must in [30,100],the default value is 30
.build());
Get audit images
xxxxxxxxxx
List<LivenessImageData> auditImageList = LivenessResult.getAuditImageList();
// data structure
public class LivenessImageData {
public final String base64Image;// Base64 format image
public final long timestamp;// Timestamp of image capture.
}
Video recording feature.
By enabling this feature, the SDK will activate video recording. After the completion of the liveness process, you can retrieve the video file using SDK methods. The video file format is .mp4. Please note that this video can only be obtained through the SDK and cannot be obtained from the backend. After using the video, it is up to you to decide whether to delete the local file.
xxxxxxxxxx
GuardianLivenessDetectionSDK.setRecordVideoSwitch(true);
GuardianLivenessDetectionSDK.setMaxRecordVideoSeconds(60);// Maximum recording duration, in seconds, valid range [2,60], default is 60 seconds.
Get video file
xxxxxxxxxx
File videoFile = LivenessResult.getVideoFile(this);
Customize the size of the returned image
xxxxxxxxxx
// Settable input range: [300,1000], unit: pixels
GuardianLivenessDetectionSDK.setResultPictureSize(600);
User binding (strongly recommended).
You can use this method to pass your user unique identifier to us, we will establish a mapping relationship based on the identifier.It is helpful for us to check the log when encountering problems.
xxxxxxxxxx
GuardianLivenessDetectionSDK.bindUser(String userId)
Turn on occlusion detection
If you want to enable occlusion detection, please call the following method after initializing the SDK to set it
xxxxxxxxxx
GuardianLivenessDetectionSDK.isDetectOcclusion(true)
Start the liveness detection and obtain the result.
Each time the liveness detection is successful, a unique livenessId and a clear photo of 600*600 pixels for this detection will be returned.
You need to give the livenessId to your server, and the server will call openAPI to get the score of this detection.
You can get the image directly through the methods provided by the SDK, or you can call the openAPI from the server.
Important: After each liveness session, please make sure to save the eventId. If users have any questions or issues during the usage, please provide us with the eventId for troubleshooting. Without the eventId, it will be difficult to investigate the problem.
xxxxxxxxxx
public class SomeActivity extends Activity{
/**
* requestCode
*/
public static final int REQUEST_CODE_LIVENESS = xxxx;
/**
* start Liveness Activity
*/
private void startLivenessActivity() {
Intent intent = new Intent(this, LivenessActivity.class);
// Set camera type, default is front camera
GuardianLivenessDetectionSDK.setCameraType(CameraType.FRONT);// The back camera is CameraType.BACK
startActivityForResult(intent, REQUEST_CODE_LIVENESS);
}
/**
* get Liveness result
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_LIVENESS) {
// Please make sure to save eventId for contacting us for troubleshooting purposes
String eventId = LivenessResult.getEventId();
File videoFile = LivenessResult.getVideoFile(this);// The video file
if (LivenessResult.isSuccess()) {// Success
String livenessId = LivenessResult.getLivenessId();// livenessId
boolean pay = LivenessResult.isPay();// pay status
Bitmap livenessBitmap = LivenessResult.getLivenessBitmap();// picture(Far)
Bitmap nearBitmap = LivenessResult.getNearBitmap();// picture(Near)
List<LivenessImageData> auditImageList = LivenessResult.getAuditImageList();// Audit images
} else {// Failure
String errorCode = LivenessResult.getErrorCode();// error code
String errorMsg = LivenessResult.getErrorMsg();// error message
...
}
}
}
}
errorCode | Resource ID | Description |
---|---|---|
ACTION_TIMEOUT | liveness_failed_reason_timeout | Detection timeout |
MULTIPLE_FACE | liveness_failed_reason_multipleface | Multiple faces detected |
FACE_MISSING | liveness_failed_reason_facemissing_blink_mouth | Face lost during the detection process |
MUCH_ACTION | fail_reason_much_action | Excessive face movement during the detection process |
USER_GIVE_UP | User canceled the detection | |
NO_RESPONSE | Network request failed | |
DEVICE_NOT_SUPPORT | liveness_device_not_support | Current device does not support liveness detection |
UNDEFINED | Other undefined errors | |
AUTH_PARAMETER_ERROR | Authentication error: please make sure the license is successfully initialized | |
AUTH_IAM_FAILED | Authentication error: please make sure the license is successfully initialized | |
WEAK_LIGHT | liveness_weak_light | The light is too weak |
STRONG_LIGHT | liveness_too_light | The light is too strong |
AUTH_BAD_NETWORK | Failed to authorize network | |
CHECKING_BAD_NETWORK | Network failed to upload image | |
MODEL_ERROR | Model error | |
ALREADY_INIT | Repeated loading | |
NO_UPLOAD_IMAGE | Failed to capture the best uploaded image | |
AUTH_TICKET_DISABLE | Ticket is expired | |
AUTH_ACCOUNT_ACCESS_DENIED | Access for this account is denied | |
...(Other server side error codes) |
You are allowed to customize the UI under the following constraints:
Multilingual
Currently SDK supports these languages/voice: English, Indonesian, Chinese,Vietnamese,Hendi,Thai.Automatically switch according to the current language of the mobile phone, no code setting is required.
The default language for the SDK is English. If it is not consistent with the default language of your app, please manually find the resource in "liveness/res" that corresponds to your app's default language and replace the default resource with it.
If the SDK does not automatically switch with the system language, please check your cellphone language settings and make sure that both [Region] and [Language] are switched to the corresponding language.
If it still have problems with multiple languages and the app only supports one language, you can filter out the unwanted languages by adding the following configuration to build.gradle
xxxxxxxxxx
android {
defaultConfig {
...
resConfigs("in-rID") // For example, only Indonesian is supported
}
}
Code proguard configuration
The SDK has built-in produard rules, so you don't need to do any additional configuration.
About androidx
Considering the mutually exclusive nature of
AndroidX
andandroid.support.*
packages, all the .aar of this SDK areandroid.support.*
packages. If your project is anAndroidX
package and you encounter aandroid.support.*
package conflict error when compiling, please add the following configuration to thegradle.properties
file in the root directory of your project and recompile the project and you will be able to:
xxxxxxxxxx
android.enableJetifier=true
What value should be passed as the userId in the bindUser method?
A string that can identify the current liveness event. Recommended values: user ID, username, device ID, transaction number.
This method has been removed, please use mLivenessView.isSoundPlayEnable() instead.
UNDEFINED indicates an unexpected error occurred in the SDK. Please provide the relevant video content and user ID to us for investigation.
To reduce the number of network requests, the license validity check is performed locally on the phone based on the current phone time and the license expiration time. This issue is usually caused by the user's phone time being inaccurate. Suggestions:
1. Check the accuracy of the user's phone time, and prompt the user not to modify the phone time if they have. 2. Set a longer license validity period when requesting the license.
It depends on the camera performance, there is no specific value. It is recommended to use relevant tools for detection.
Yes, it supports. You can set it to use the rear camera with this method. However, we have not fully optimized the compatibility for the rear camera, so it is not recommended to use the rear camera.
xxxxxxxxxx
GuardianLivenessDetectionSDK.setCameraType(CameraType.BACK);
AAI is not responsible for storing video files, it only supports obtaining the liveness video through the SDK. Please transmit the video properly and delete the video file on the phone according to your business needs.
This method is specific to action liveness, 3D liveness does not have this method.
Use the corresponding nd version of the core dependency:
xxxxxxxxxx
implementation 'ai.advance.mobile-sdk.android:core:5.5.nd'
When we invoke the license check, the following line of code will be executed:
xxxxxxxxxx
String result = GuardianLivenessDetectionSDK.setLicenseAndCheck("Your license string");
If the license string is too long, it will cause the constant string too long error. The best way is to store our string in a separate file instead of in a declared variable or constant.In the assets directory of your project, create a license file, insert the string into this file, and subsequently read the string from it.The code for reading the string is as follows:
xxxxxxxxxx
String readLicenseFromAssets() {
String license = null;
try {
InputStream is = getAssets().open("license");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
license = baos.toString();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return license;
}
Then, the code for checking the license would be updated as follows:
xxxxxxxxxx
String result = GuardianLivenessDetectionSDK.setLicenseAndCheck(readLicenseFromAssets());