TrustVision SDK is the android SDK for TrustVision Engine. This document is for Clients who only use the UI of the SDK. It provides these features:
TrustVisionSDK.init(jsonConfigurationByServer, languageCode);
tv_sdk.zip
, extract and put all files into a folder in android project.
Example: folder ${project.rootDir}/repo
app
root
repo
+--com
+--trustvision
+--tv_api_sdk
+--2.x.x
+--tv_api_sdk-2.x.x.aar
+--tv_api_sdk-2.x.x.pom
maven-metadata.xml
+--tv_core_sdk
+--tv_sdk
...
build.gradle
repositories {
maven { url "https://maven.google.com" }
maven { url "https://jitpack.io" } // from SDK v2.0.0.20 and above
maven { url "path/to/tvsdk/folder" }
...
}
app/build.gradle
android {
...
aaptOptions {
noCompress "tflite"
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation('com.trustvision:tv_sdk:2.x.x@aar') {
transitive = true
}
testImplementation 'junit:junit:4.12'
}
To initialize the SDK, add the following lines to your app, and it needs to be completed successfully before calling any other SDK functionalities.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TrustVisionSDK.init(jsonConfigurationByServer, languageCode);
}
Please note: The SDK requires Camera permissions to capture images. Camera permissions will be handled by the SDK if not already handled by the app.
where:
String
. The jsonConfigurationByServer is optional but recommended.
It's the setting specialized for each client from TS server.
It's the response json string get by API https://ekyc.trustingsocial.com/api-reference/customer-api/#get-client-settings.
When it's null or unmatched with the expected type then the default setting in the SDK will be used.String
the code of the language that will show and sound to user. E.g Vietnamese (vi), English (en).TrustVisionSdk.getSupportedLanguages();
TrustVisionSdk.getLanguageCode();
Allow user to change the sdk language after initialization
TrustVisionSdk.changeLanguageCode(String languageCode);
The SDK provides some built in Activities example activity to capture id, selfie, liveness...
The id capturing activity will show the camera to capture image, preview the image. To start the id capturing activity.
TVIDConfiguration.Builder builder = new TVIDConfiguration.Builder()
.setCardType(selectedCard)
.setCardSide(TVSDKConfiguration.TVCardSide.FRONT)
.setReadBothSide(false)
.setEnableSound(false)
.setEnablePhotoGalleryPicker(false)
.setEnableTiltChecking(false)
.setSkipConfirmScreen(false);
TVIDConfiguration configuration = builder.build();
Options:
TVCardType
. List of supported cards can be found by TrustVisionSDK.getCardTypes()
.TVCardSide
. Card side to capture.boolean
. If true then the sdk will capture both side if possible; otherwise, then the card side defined in cardSide will be used.boolean
. Sound should be played or not.boolean
. Allow user select id card image from phone gallery.boolean
. Check if the phone is parallel to the ground before taking the id card photo or not.boolean
. Control whether the SDK should skip the confirmation screen.TrustVisionSDK.startIDCapturing(context, configuration, new TVIDCapturingCallBack() {
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
}
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
}
@Override
public void onCanceled() {
}
});
where:
TVCapturingCallBack
. It is an interface that has 3 methodsNewFrameBatchCallback
. can be called multiple times during the capturing to return frame data.FrameBatch
String
. batch id generated by TV SDKList<TVFrameClass>
. batch frame to pushMap<String, String>
. batch metadata to pushSet<String>
. For debugging purpose onlyonSuccess
method has one parameter.TVDetectionResult
. has the following methods:ErrorCallback
. Will be called when an error has occurred during the capturing.TVDetectionError
CancellationCallback
. Will be called when the journey has been cancelled (e.g user clicked on back button...)With each batch that returned by onNewFrameBatch(FrameBatch)
callback,
call the below api to upload the data to server, and store the frame batch id that responses from the API, keep it corresponding with frameBatch.getId()
- local id
https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-frame-batch
For example:
// this dictionary will be used for ID Tampering Verification
Map frontCardFrameBatchIdsDictionary = new HashMap<String, String>();
Map backCardFrameBatchIdsDictionary = new HashMap<String, String>();
// frameBatchIdsDictionary.put(
// key = <id_returned_from_sdk>,
// value = <id_responded_from_server>
// );
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
Gson gson = new Gson();
String framesStr = gson.toJson(frameBatch.getFrames());
Map<String, Object> params = new HashMap<>();
params.put("frames", framesStr);
params.put("metadata", frameBatch.getMetadata());
params.put("label", "video");
String jsonToBeUploaded = gson.toJson(params);
// upload frame batch to server using this api:
// https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-videoaudioframes
YourResponseObject uploadingResult = yourMethodToUploadFrameBatch(jsonToBeUploaded);
// Keep the id that generated by the SDK corresponding with the one responded from server
if (cardSide == TVSDKConfiguration.TVCardSide.FRONT) {
frontCardFrameBatchIdsDictionary.put(
key = frameBatch.batchId,
value = uploadingResult.fileId
);
} else {
backCardFrameBatchIdsDictionary.put(
key = frameBatch.batchId,
value = uploadingResult.fileId
);
}
}
// These lists contain all valid frame batch ids that responded by server
List<String> validFrontCardServerFrameBatchIds;
List<String> validBackCardServerFrameBatchIds;
@Override
public void onSuccess(TVDetectionResult result) {
// result.livenessFrameBatchIds is null when Frame Recording feature is disabled by client settings.
// Wait until every Frame batch has been uploaded to server before calling this
if(everyFrameBatchUploadingCompleted) {
if(result.frontCardFrameBatchIds != null) {
validFrontCardServerFrameBatchIds = removeRedudantFrameBatchIds(frontCardFrameBatchIdsDictionary, result.frontCardFrameBatchIds);
}
if(result.backCardFrameBatchIds != null) {
validBackCardServerFrameBatchIds = removeRedudantFrameBatchIds(backCardFrameBatchIdsDictionary, result.backCardFrameBatchIds);
}
}
}
private List<String> removeRedudantFrameBatchIds(Map<String, String> batchIdsDictionary, Set<String> validIdsFromSDK) {
Iterator<Map.Entry<String, String>> iter = batchIdsDictionary.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
if(!validIdsFromSDK.contains(entry.getKey())) {
iter.remove();
}
}
return batchIdsDictionary.values();
}
Use this API https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-image The images should be uploaded as JPEG data with 100% quality. For example:
String frontCardId;
String backCardId;
String qrId;
@Override
public void onSuccess(TVDetectionResult result) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// With front side
if (result.getFrontCardImage() && result.getFrontCardImage().getImage() != null) {
// 100 quality is required
result.getFrontCardImage().getImage().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] dataToUpload = stream.toByteArray();
frontCardId = yourMethodToUploadImage(dataToUpload);
}
// With back side
if (result.getBackCardImage() && result.getBackCardImage().getImage() != null) {
// 100 quality is required
result.getBackCardImage().getImage().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] dataToUpload = stream.toByteArray();
backCardId = yourMethodToUploadImage(dataToUpload);
}
// With QR image (Available from v2.0.6.9)
// In case the QR capturing feature is enabled, and `result.getCardQrImage()` is null then
// the user will be notified so they can choose to re-capture their ID card.
if (result.getCardQrImage() && result.getCardQrImage().getImage() != null) {
// 100 quality is required
result.getCardQrImage().getImage().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] dataToUpload = stream.toByteArray();
qrId = yourMethodToUploadImage(dataToUpload);
}
}
API request parameters:
{
"file": "<byte[] dataToUpload>",
"label": "<proper label, check the API document for detail>"
}
Call this API https://ekyc.trustingsocial.com/api-reference/customer-api/#request-detect-id-card-tampering with params:
{
"image": {
"id": "<frontCardId>"
},
"image2": {
"id": "<backCardId>"
},
"qr1_images": [{
"id": "<qrId>"
}],
"card_type": "<result.cardType.getCardId()>",
"videos": [{
"id": "<validFrontCardServerFrameBatchIds.get(index)>"
},
{
"id": "<validFrontCardServerFrameBatchIds.get(index + 1)>"
},
...
{
"id": "<validBackCardServerFrameBatchIds.get(index)>"
},
{
"id": "<validBackCardServerFrameBatchIds.get(index + 1)>"
},
...
]
}
if result.getFrontIdQr().isRequired()
is true then result.getFrontIdQr().getImages()
array should be non-empty. Otherwise, clients should be warned to re-capture id card photos.
QR images will be uploaded with this api: https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-image
val data : ByteArray = convertBitmapToByteArray(tvDetectionResult.cardQrImage?.image)
val metadata : String = tvDetectionResult.cardQrImage?.metaData
val label : String = tvDetectionResult.cardQrImage?.label
The selfie capturing activity will show the camera to capture image, preview the image, verify liveness. To start the selfie capturing activity.
TVSelfieConfiguration.Builder builder = new TVSelfieConfiguration.Builder()
.setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
.setEnableSound(false)
.setLivenessMode(TVLivenessMode.PASSIVE)
.setSkipConfirmScreen(false);
Options:
TVCameraOption
. Camera modeboolean
. Sound should be played or notTVLivenessMode
. Liveness verification modeboolean
. Control whether the SDK should skip the confirmation screen.TrustVisionSDK.startSelfieCapturing(context, languageCode, builder.build(), new TVCapturingCallBack() {
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
}
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
}
@Override
public void onCanceled() {
}
});
where:
TVCapturingCallBack
. It is an interface that has 3 methodsNewFrameBatchCallback
. can be called multiple times during the capturing to return frame data.FrameBatch
String
. batch id generated by TV SDKList<TVFrameClass>
. batch frame to pushMap<String, String>
. batch metadata to pushSet<String>
. For debugging onlyonSuccess
method has one parameter.TVDetectionResult
. has the following methods:ErrorCallback
. Will be called when an error has occurred during the capturing.TVDetectionError
CancellationCallback
. Will be called when the journey has been cancelled (e.g user clicked on back button...)With each batch that returned by onNewFrameBatch(FrameBatch)
callback,
call the below api to upload the data to server, and store the frame batch id that responses from the API, keep it corresponding with frameBatch.getId()
- local id
https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-frame-batch
For example:
// this dictionary will be used for Liveness verification
Map selfieFrameBatchIdsDictionary = new HashMap<String, String>();
// frameBatchIdsDictionary.put(
// key = <id_returned_from_sdk>,
// value = <id_responded_from_server>
// );
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
Gson gson = new Gson();
String framesStr = gson.toJson(frameBatch.getFrames());
Map<String, Object> params = new HashMap<>();
params.put("frames", framesStr);
params.put("metadata", frameBatch.getMetadata());
params.put("label", "video");
String jsonToBeUploaded = gson.toJson(params);
// upload frame batch to server using this api:
// https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-videoaudioframes
YourResponseObject uploadingResult = yourMethodToUploadFrameBatch(jsonToBeUploaded);
// Keep the id that generated by the SDK corresponding with the one responded from server
frameBatchIdsDictionary.put(
key = frameBatch.batchId,
value = uploadingResult.fileId
);
}
// This list contains all valid frame batch ids that responded by server
List<String> validServerFrameBatchIds;
@Override
public void onSuccess(TVDetectionResult result) {
// result.livenessFrameBatchIds is null when Frame Recording feature is disabled by client settings.
// Wait until every Frame batch has been uploaded to server before calling this
if(everyFrameBatchUploadingCompleted) {
if(result.livenessFrameBatchIds != null) {
validServerFrameBatchIds = removeRedudantFrameBatchIds(selfieFrameBatchIdsDictionary, result.livenessFrameBatchIds);
}
}
}
private List<String> removeRedudantFrameBatchIds(Map<String, String> batchIdsDictionary, Set<String> validIdsFromSDK) {
Iterator<Map.Entry<String, String>> iter = batchIdsDictionary.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String, String> entry = iter.next();
if(!validIdsFromSDK.contains(entry.getKey())) {
iter.remove();
}
}
return batchIdsDictionary.values();
}
Use this api https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-image
to get image ids with the inputs are the elements of result.getSelfieImages()
The images should be uploaded as JPEG data with 100% quality.
For example:
// These lists of image ids will be used in Liveness Verification
List<String> frontalImageIds = new ArrayList<>();
List<String> gestureImageIds = new ArrayList<>();
@Override
public void onSuccess(TVDetectionResult result) {
handleSelfieImages(result.getSelfieImages());
}
private void handleSelfieImages(List<SelfieImage> selfieImages) {
for(selfieImage: selfieImages) {
// Handle frontal images
if(selfieImage.getFrontalImage() != null && selfieImage.getFrontalImage().getImage() != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// 100 quality is required
selfieImage.getFrontalImage().getImage().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] frontalImageByteArray = stream.toByteArray();
// frontalImageId is the id of the image, returned from server when the uploading API is completed successfully
String frontalImageId = yourUploadImageMethod(frontalImageByteArray);
frontalImageIds.add(frontalImageId);
}
// Handle gesture images
if(selfieImage.getGestureImage() != null && selfieImage.getGestureImage().getImage()!=null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// 100 quality is required
selfieImage.getGestureImage().getImage().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] gestureImageByteArray = stream.toByteArray();
// gestureImageId is the id of the image, returned from server when the uploading API is completed successfully
String gestureImageId = yourUploadImageMethod(gestureImageByteArry);
gestureImageIds.add(gestureImageId);
}
}
}
Upload Image API request, parameters:
{
"file": "<byte[] dataToUpload>",
"label": "<proper label, check the API document for detail>"
}
API document: https://ekyc.trustingsocial.com/api-reference/customer-api/#verify-face-liveness
Call the above api with below parameters:
images
field{
"images": [
{
"id": "<frontalImageIds.get(index)>"
},
{
"id": "<frontalImageIds.get(index + 1)>"
},
...
]
}
gesture_images
field{
"gesture_images": [
{
"gesture": "<result.getSelfieImages().get(index).getGestureType().toGestureType().toLowerCase()>",
"images": [{
"id": "<gestureImageIds.get(index)>"
}]
},
{
"gesture": "<result.getSelfieImages().get(index + 1).getGestureType().toGestureType().toLowerCase()>",
"images": [{
"id": "<gestureImageIds.get(index + 1)>"
}]
},
...
]
}
videos
field{
"videos": [
{
"id": "<validServerFrameBatchIds.get(index)>"
},
{
"id": "<validServerFrameBatchIds.get(index + 1)>"
},
...
]
}
metadata
field{
"metadata": "<result.getLivenessMetadata()>"
}
// [FlowStartingFunc]: startIdCapturing, startSelfieCapturing
TrustVisionSDK.[FlowStartingFunc](..., builder.build(), new TVCapturingCallBack() {
@Override
public void onError(TVDetectionError error) {
String message = error.getErrorDescription();
Log.d("", message);
showToast(message);
///////////////////////////////////////
// ERROR HANDLER
int code = error.getErrorCode();
String description = error.getErrorDescription();
switch code {
case TVDetectionError.DETECTION_ERROR_PERMISSION_MISSING:
// No camera permission.
case TVDetectionError.DETECTION_ERROR_CAMERA_ERROR:
// The camera can't be opened.
case TVDetectionError.DETECTION_ERROR_SDK_INTERNAL:
// The SDK has an unexpected error.
}
}
@Override
public void onSuccess(TVDetectionResult result) {
}
});
Method | Type | description |
---|---|---|
isLive | Boolean | Determines whether the selfie is live or not |
getScore() | float | The score from 0 to 1 |
Method | Type | description |
---|---|---|
getSelfieImages() | List <SelfieImage > | List of images that each item contains the bitmap of the selfie image |
getSelfieFrameBatchIds() | Final list of Selfie's local frame batch IDs. Local batch ids that not in this list are invalid and their corresponding server IDs shouldn't be used | |
getLivenessMetadata() | JSONObject | Collected data during liveness checking process |
Method | Type | description |
---|---|---|
getFrontCardImage() | TVImageClass | Contains bitmap of the front image |
getBackCardImage() | TVImageClass | Contains bitmap of the back image |
getQRImage() | TVImageClass | Contains bitmap of the QR image |
getFrontCardFrameBatchIds() | Set<String > | Final list of front side's local frame batch IDs. Local batch ids that not in this list are invalid and their corresponding server IDs shouldn't be used |
getBackCardFrameBatchIds() | Set<String > | Final list of back side's local frame batch IDs. Local batch ids that not in this list are invalid and their corresponding server IDs shouldn't be used |
Method | Type | description |
---|---|---|
getError() | TVDetectionError | The error found when doing any detection |
Method | Type | description |
---|---|---|
getGestureType() | FaceDetectionType | Gesture type of the selfie image |
getFrontalImage() | TVImageClass | Frontal image of the selfie image |
getGestureImage() | TVImageClass | Gesture image of the selfie image |
Method | Type | description |
---|---|---|
getType() | int | Represent a gesture type |
int NEUTRAL = 1
int TURN_LEFT = 5
int TURN_RIGHT = 6
int FACE_UP = 7
int FACE_DOWN = 8
Method | Type | description |
---|---|---|
getLabel() | String | Label of the Image class. |
getImage() | Bitmap | Captured Bitmap |
Method | Type | description |
---|---|---|
getErrorCode() | int | Error code |
getErrorDescription() | String | Error description |
Error code is one of the below list
int TVDetectionError.DETECTION_ERROR_PERMISSION_MISSING = 1004
int TVDetectionError.DETECTION_ERROR_CAMERA_ERROR = 1005
int TVDetectionError.DETECTION_ERROR_SDK_INTERNAL = 1007
Method | Type | description |
---|---|---|
getFrames() | List <TVFrameClass > | Recorded frames during the capturing |
getId() | String | Local ID of the batch, to be corresponds with the ID responded from server after the frame batch is pushed |
getMetadata() | Map<String, String> | Metadata of the batch |
getValidVideoIds() | Set<String > | For debugging purpose only |
Method | Type | description |
---|---|---|
getFramesBase64() | String | The data of the frame as a base64 String |
getIndex() | String | Index of this frame in the list of recorded frames |
getLabel() | String | Label of this frame |
Will be called in case failed. Parameters:
TVDetectionError
.Will be called in case the sdk is cancelled. No parameters.