• About TrustVision
  • Android SDK
  • Flutter SDK
  • React Native SDK
  • iOS SDK
  • Web SDK
  • API Client Libraries
  • Integration Case Studies
  • TS eKYC/FA App
  • eKYC Platform
TrustVision API Documentation

Android v2.1.x UI Only

OVERVIEW

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:

  • Capture ID and Selfie.
  • Liveness checking.

Specifications

  • Gradle Version 6.5
  • Tested with Gradle Plugin for Android Studio - version 4.1.1
  • minSdkVersion 21
  • targetSdkVersion 30

Example Project

  • Please refer to the sample project provided in the Example to get an understanding of the implementation process.
java
TrustVisionSDK.init(jsonConfigurationByServer, languageCode);
  • Build and run the example app

Integration Steps

1. Adding the SDK to your project

  • Get library file 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
...
  • Add the following set of lines to the Project (top-level) build.gradle
groovy
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" }
    ...
}
  • Add the following set of lines to your app/build.gradle
groovy
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'

}

2. Initialize and config SDK

2.0. Initialize SDK

To initialize the SDK, add the following lines to your app, and it needs to be completed successfully before calling any other SDK functionalities.

java
@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:

  • jsonConfigurationByServer: 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.
  • languageCode: String the code of the language that will show and sound to user. E.g Vietnamese (vi), English (en).

2.1. Config

2.1.0 Language code
2.1.0.0 Get supported language codes list
java
TrustVisionSdk.getSupportedLanguages();
2.1.1.1 Get language code in use
java
TrustVisionSdk.getLanguageCode();
2.1.1.2

Allow user to change the sdk language after initialization

java
TrustVisionSdk.changeLanguageCode(String languageCode);

3. Start the SDK

The SDK provides some built in Activities example activity to capture id, selfie, liveness...

3.0. Capture the ID

The id capturing activity will show the camera to capture image, preview the image. To start the id capturing activity.

3.0.1. Set config parameters
java
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:

  • setCardType: TVCardType. List of supported cards can be found by TrustVisionSDK.getCardTypes().
  • setCardSide: TVCardSide. Card side to capture.
  • setReadBothSide boolean. If true then the sdk will capture both side if possible; otherwise, then the card side defined in cardSide will be used.
  • setEnableSound: boolean. Sound should be played or not.
  • setEnablePhotoGalleryPicker: boolean. Allow user select id card image from phone gallery.
  • setEnableTiltChecking: boolean. Check if the phone is parallel to the ground before taking the id card photo or not.
  • setSkipConfirmScreen: boolean. Control whether the SDK should skip the confirmation screen.
3.0.2. Start id capturing activity from configuration
java
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:

  • context: is the context of the current Activity being displayed
  • configuration: the configuration would like to pass to id capturing activity
  • callback: is an object of type TVCapturingCallBack . It is an interface that has 3 methods
    • onNewFrameBatch: NewFrameBatchCallback. can be called multiple times during the capturing to return frame data.
      • frameBatch: FrameBatch
        • getId(): String. batch id generated by TV SDK
        • getFrames(): List<TVFrameClass>. batch frame to push
        • getMetadata(): Map<String, String>. batch metadata to push
        • getValidVideoIds() Set<String>. For debugging purpose only
    • onSuccess method that will be called in case of success. The onSuccess method has one parameter.
      • result : TVDetectionResult. has the following methods:
        • getFrontCardImage()
        • getBackCardImage()
        • getQRImage()
    • onError: ErrorCallback. Will be called when an error has occurred during the capturing.
      • error: TVDetectionError
    • onCanceled: CancellationCallback. Will be called when the journey has been cancelled (e.g user clicked on back button...)
3.0.3. Handle onNewFrameBatch callback

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:

java
// 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
        );
    }
}
3.0.4. Handle ID capturing results
3.0.4.1 Remove redundant frame batch ids
Java
// 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();
}
3.0.4.2. Get Image Ids to be used in a particular use case

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:

java
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:

json
{
  "file": "<byte[] dataToUpload>",
  "label": "<proper label, check the API document for detail>"
}
3.0.4.3. Check ID Tampering

Call this API https://ekyc.trustingsocial.com/api-reference/customer-api/#request-detect-id-card-tampering with params:

json
{
    "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)>"
      },
      ...
    ]
}
3.0.4.4 Upload QR images

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

kotlin
val data : ByteArray = convertBitmapToByteArray(tvDetectionResult.cardQrImage?.image)
val metadata : String = tvDetectionResult.cardQrImage?.metaData
val label : String = tvDetectionResult.cardQrImage?.label

3.1. Capture the selfie

The selfie capturing activity will show the camera to capture image, preview the image, verify liveness. To start the selfie capturing activity.

3.1.1. Set config parameters
java
TVSelfieConfiguration.Builder builder = new TVSelfieConfiguration.Builder()
    .setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
    .setEnableSound(false)
    .setLivenessMode(TVLivenessMode.PASSIVE)
    .setSkipConfirmScreen(false);

Options:

  • setCameraOption: TVCameraOption. Camera mode
  • setEnableSound: boolean. Sound should be played or not
  • setLivenessMode: TVLivenessMode. Liveness verification mode
  • setSkipConfirmScreen: boolean. Control whether the SDK should skip the confirmation screen.
3.1.2. Start selfie capturing activity from configuration
java
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:

  • context: is the context of the current Activity being displayed
  • languageCode: the code of the language that will show on UI and it's also the language of the sound that will guide user. Currently support Vietnamese (vi) and English (en)
  • configuration: the configuration would like to pass to selfie capturing activity
  • callback: is an object of type TVCapturingCallBack . It is an interface that has 3 methods
    • onNewFrameBatch: NewFrameBatchCallback. can be called multiple times during the capturing to return frame data.
      • frameBatch: FrameBatch
        • getId(): String. batch id generated by TV SDK
        • getFrames(): List<TVFrameClass>. batch frame to push
        • getMetadata(): Map<String, String>. batch metadata to push
        • getValidVideoIds() Set<String>. For debugging only
    • onSuccess method that will be called in case of success. The onSuccess method has one parameter.
      • result : TVDetectionResult. has the following methods:
        • getSelfieImages()
        • getSelfieFrameBatchIds()
        • getLivenessMetadata()
    • onError: ErrorCallback. Will be called when an error has occurred during the capturing.
      • error: TVDetectionError
    • onCanceled: CancellationCallback. Will be called when the journey has been cancelled (e.g user clicked on back button...)
3.1.3. Handle onNewFrameBatch callback

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:

java
// 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
    );
}
3.1.4. Handle selfie results
3.1.4.1 Remove redundant frame batch ids
Java
// 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();
}
3.1.4.2. Get Image Ids

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:

java
// 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:

json
{
  "file": "<byte[] dataToUpload>",
  "label": "<proper label, check the API document for detail>"
}
3.1.4.3. Liveness Verification

API document: https://ekyc.trustingsocial.com/api-reference/customer-api/#verify-face-liveness

Call the above api with below parameters:

  1. images field
json
{
  "images": [
    {
      "id": "<frontalImageIds.get(index)>"
    },
    {
      "id": "<frontalImageIds.get(index + 1)>"
    },
    ...
  ]
}
  1. gesture_images field
json
{
  "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)>"
      }]
    },
    ...
  ]
}
  1. videos field
json
{
  "videos": [
    {
      "id": "<validServerFrameBatchIds.get(index)>"
    },
    {
      "id": "<validServerFrameBatchIds.get(index + 1)>"
    },
    ...
  ]
}
  1. metadata field
json
{
  "metadata": "<result.getLivenessMetadata()>"
}

3.2. Error handling:

java
// [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) {

    }
});

API Interface

1. TVLivenessResult

MethodTypedescription
isLiveBooleanDetermines whether the selfie is live or not
getScore()floatThe score from 0 to 1

2. TVDetectionResult

Selfie
MethodTypedescription
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()JSONObjectCollected data during liveness checking process
ID Card
MethodTypedescription
getFrontCardImage()TVImageClassContains bitmap of the front image
getBackCardImage()TVImageClassContains bitmap of the back image
getQRImage()TVImageClassContains 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
MethodTypedescription
getError()TVDetectionErrorThe error found when doing any detection

3. SelfieImage

MethodTypedescription
getGestureType()FaceDetectionTypeGesture type of the selfie image
getFrontalImage()TVImageClassFrontal image of the selfie image
getGestureImage()TVImageClassGesture image of the selfie image

4. FaceDetectionType

MethodTypedescription
getType()intRepresent a gesture type
java
int NEUTRAL = 1
int TURN_LEFT = 5
int TURN_RIGHT = 6
int FACE_UP = 7
int FACE_DOWN = 8

5. TVImageClass

MethodTypedescription
getLabel()StringLabel of the Image class.
getImage()BitmapCaptured Bitmap

6. TVDetectionError

MethodTypedescription
getErrorCode()intError code
getErrorDescription()StringError description

Error code is one of the below list

java
int TVDetectionError.DETECTION_ERROR_PERMISSION_MISSING = 1004
int TVDetectionError.DETECTION_ERROR_CAMERA_ERROR = 1005
int TVDetectionError.DETECTION_ERROR_SDK_INTERNAL = 1007

7. TVCameraOption (Enum)

  • TVCameraOption.FRONT: Use front camera
  • TVCameraOption.BACK: Use back camera
  • TVCameraOption.BOTH: The screen will have a button to switch between front & back camera

8. TVLivenessMode (Enum)

  • TVLivenessMode.NONE: no liveness verification. Just capture the selfie.
  • TVLivenessMode.PASSIVE: Use texture-based approach.
  • TVLivenessMode.ACTIVE: Use challenge-response approach. User needs to follow and finish all steps when capturing selfie such as turn left, right, up, smile, open mouth...

9. TVDefaultCameraSide (Enum)

  • TVDefaultCameraSide.FRONT
  • TVDefaultCameraSide.BACK

10. FrameBatch

MethodTypedescription
getFrames()List <TVFrameClass>Recorded frames during the capturing
getId()StringLocal 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

11. TVFrameClass

MethodTypedescription
getFramesBase64()StringThe data of the frame as a base64 String
getIndex()StringIndex of this frame in the list of recorded frames
getLabel()StringLabel of this frame

12. ErrorCallback (Callback)

Will be called in case failed. Parameters:

  • error: TVDetectionError.

13. CancellationCallback (Callback)

Will be called in case the sdk is cancelled. No parameters.