Android SDK Integration (Beta)

Android SDK Errors

Our Android DI SDK reports errors using a numeric code and a message. These errors are the following:

  • 20001: "API Key is missing"
  • 20002: "Process canceled"
  • 20003: "Identity process has no next steps"
  • 20004: "Step is invalid"
  • 20005: "Identity process is invalid"
  • 20006: "Validation declined"
  • 20007: "Validation expired"
  • 20008: "Validation failed due to system error"
  • 20009: "Validation failed"
  • 20010: "Process cancelled by the user"
  • 20011: "Camera permission denied, process cannot continue"
  • 20012: "File upload link is invalid"
  • 20013: "Process was interrupted. Please try again"
  • 20014: “Missing module.”
  • 20015: “This flow is not available at the moment”
  • 20016: "The identity process is taking too long to finish. Please try polling the result from the API"
  • 20500: "Unexpected error"
  • 30001: "File could not be uploaded. Please try again"
  • 30002: "Face not detected in document. Please try again"
  • 30003: "The temporary api key has expired. Please try again"

Getting started

Add the SDK dependencies

Add the SDK dependencies to your app’s build.gradle file add the necessary packages of the DI SDK to start the project, for example:

dependencies {
  implementation 'com.truora:di.core:<version>'
  ...
}

You must specify the version using semantic versioning (e.g., 0.0.1).

Currently, we support the following packages:

  • com.truora.di-core (REQUIRED): Package for managing core functionalities of the SDK, including UI, API communication, errors and the identity process. This package is required to start the SDK for your DI flow.
  • com.truora.di.document (OPTIONAL): Package used when identity flow includes document validation, which contains the instructions, camera and image manipulation of the document photos.
  • com.truora.di.face (OPTIONAL): Package used when identity flow includes face match or liveness validations, which contains the instructions, and camera (image and video) of the face media.

Start the SDK

First, start the SDK in your code by using our core package, for example:

int TRUORA_REQUEST_CODE = 1;

try {
    TruoraIdentityConfig truoraConfig =
            TruoraIdentityConfig.builder("REPLACE_WITH_GENERATED_API_KEY")
                    .build();

    TruoraIdentitySDK truoraIdentitySDK = new TruoraIdentitySDK(truoraConfig);
    truoraIdentitySDK.startActivityForResult(this, TRUORA_REQUEST_CODE);
} catch (TruoraException e) {
    // Handle exception here using e.getMessage() method
}

To start our SDK you need to create an instance of TruoraIdentitySDK. Keep in mind that:

  • You need to provide a generated API Key that includes the flow_id to use our SDK. (Here are some instructions to create the temporary API Key and check the API key management section below for some tips regarding its management).
  • You also need a unique code (TRUORA_REQUEST_CODE in the example) so that you can receive the result of the SDK in your app. Bear in mind that our startActivityForResult method starts a new activity that will manage all the authentication flow and later return a response.

Result handling

To handle the result of the SDK make sure to validate the requestCode to be the one you defined for starting the SDK (in this case TRUORA_REQUEST_CODE) and to use our built-in handleActivityResult function inside your callback to receive the activity’s result. The identity process will be returned in case that the process finished successfully, or a TruoraException in case something failed. For example:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);

   if (requestCode != TRUORA_REQUEST_CODE) {
       return;
   }

   if (truoraIdentitySDK == null) {
       handleIntent(data);
       return;
   }

    truoraIdentitySDK.handleActivityResult(resultCode, data, new TruoraResultListener() {
        @Override
       public void onFinish(IdentityProcess identityProcess) {
           // handle identity process
        }

       @Override
       public void onError(TruoraException e) {
           // handle error
        }
    });
}

In certain occasions (like when the user disables camera permissions) the activity is ended by the OS. Hence, make sure the instance truoraIdentitySDK is still valid (like in lines 6 to 8 in the previous snippet). If it's not, you can obtain the error or identity process from the Intent extras as shown on the snippet below.

private void handleIntent(Intent data) {
    Bundle extras = data.getExtras();

    if (extras == null) {
        return;
    }

    Object exception = extras.get(TruoraKeys.EXTRA_TRUORA_EXCEPTION_KEY);
    if (exception != null && exception.getClass() == TruoraException.class) {
        // handle error
    }

    Object identityProcess = extras.get(TruoraKeys.EXTRA_IDENTITY_PROCESS_KEY);
    if (identityProcess != null && identityProcess.getClass() == IdentityProcess.class) {
        // handle identity process
    }
}

For handling errors we recommend taking a look into the codes and respective messages for the Truora Exception(See SDK Errors above). You can get this data by calling the getCode() and getMessage() methods of the returned object

Requirements

  • Min SDK version: Android API 21 level (Android Lollipop - Android 5.0)
  • Smartphone with selfie camera (for Face Match and Face Liveness steps)

Description

SDK Sizes

We used a Sample App and generated the apk with the different modules of our SDK through Android Studio, resulting in the following calculated sizes:

Application APK Size Download Size
App without modules 7.5MB 7MB
App with Core module 10.8MB 10MB
App with Core and Doc module 12.1MB 11.2MB
App with Core and Face module 19.1MB 18.1MB
App with Core, Doc and Face 20.4MB 18.9MB

The SDK sizes (apk size collected from Android Studio APK Analyzer tool) are as follows:

  • com.truora.di-core: 3.3MB
  • com.truora.di-document: 1.3MB
  • com.truora.di-face: 8.3MB

FYI: The large size of the di-face module is caused by the face recognition gifs that are stored in the apk resources. In this module we have around 7MB of gif media.

Tips

API Key Management

The code you develop for any of your mobile apps is readable. Any client can retrieve the installed APK file, decode it and read the code stored there; and, in case you are hardcoding secret/API keys, they are visible. This is a high security risk, thus we do not recommend leaving these keys hardcoded in your code.

There are multiple ways to hide your secret keys in your app, most involve leaving them in a separate file or obscuring the code itself. Some examples of these can be found in this guide.

Public FAQ

What's the minimum Android version supported by the SDK? Android Lollipop (Android 5.0). Android API 21 level

What is the size of the SDK? com.truora.di-core: 3.3MB com.truora.di-document: 1.3MB com.truora.di-face: 8.3MB

Which validators are supported by the SDK? We currently support:

  • Document validation
  • Facematch validation

What's the difference between Truora Api Key and Digital Identity Api Key? The Truora Api Key is the key you need to use to generate the Digital Identity Api Key. The Digital Identity Api Key is a temporary key that is valid for 15 minutes only.

How do I create a Digital Identity Api Key? Follow the instructions from the docs and remember to set the key type as sdk:

key_type: sdk

Why do I need a Digital Identity Api Key? Can I use the Truora Api Key instead? You can only use the Truora Api Key if you create it with a given flow_id, but this is not recommended for production code. For security reasons we recommend using the Digital Identity Api key because it is temporary. It will prevent bad actors from using it at any given time in the future.

Do I need to integrate all available SDKs? No, you only need to integrate 'com.truora:di.core' and dependencies corresponding to the validators you want to support.

Common errors

I'm seeing a 'This flow is not available at the moment' error (code: 20015). What does this mean? The flow you are using includes a step that we don't support in the SDK. Please try using a different flow or updating your flow with supported validators.

I'm seeing a 'File upload link is invalid' error (code: 20012). What does this mean? The link to upload the document photo or the face photo is only valid for 5 minutes. If you see this error, it means that the link has expired and you need to start the process again.

I'm seeing a 'Missing module' error (code: 20014). What does this mean? This error means that you are missing a dependency in your project. For example, if you are using a flow that contains document validation, you are most likely missing the document validation (com.truora:di.doc) dependency.

I'm seeing a 'Process was interrupted. Please try again' error (code: 20013). What does this mean? This error means that the main activity of the SDK (the one your app calls to start and manage the identity process) was destroyed without properly finishing and there is no way to recover that data. The only thing we can do in this scenario is to try again.

iOS SDK Integration (Temporary)

The main goal with this integration flow is to connect a mobile app with our no-code web solution located in https://identity.truora.com. Mainly we will:

  • Create a temporary API Key with the required configuration as shown here.
  • Open a webview with the url as https://identity.truora.com?token=<Temporary API Key> and allow the user to complete the flow in his/her cellphone.
  • Capture the redirect event to avoid loading the specified URL and do something with the extracted data.

Webview

In the case of iOS with Swift we should use two protocols for our ViewController:

  • WKUIDelegate: Specify that the ViewController is going to be a webview and handle the loading the view
  • WKNavigationDelegate: Specify how the navigation will be handled (redirects, for example).

This config can be done in the following way:

import UIKit
import WebKit

class DIWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    var webView: WKWebView!
    var identityUrl: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        let myURL = URL(string: identityUrl)
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.allowsInlineMediaPlayback = true

        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
    }

It’s worth noting that the URL is loaded with the “load” method of the webview.

Redirect event

For managing the redirect event we can just create a webView function that is supported since we are implementing WKNavigationDelegate:

// Handle navigation actions from the web view.
    func webView(_ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

        guard let requestUrl = navigationAction.request.url else {
            // We're not being redirected, so load the URL.
            decisionHandler(.allow)
            return
        }

        // Check if we are being redirected to our `redirectUri`. This happens once verification is completed.
        let redirectUri = requestUrl.absoluteString
        guard(redirectUri.starts(with: TruoraConstants.redirectUrl)) else {
            // We're not being redirected, so load the URL.
            decisionHandler(.allow)
            return
        }

        // Capture redirect URL event at the end of the process to read data

        // At this point we're done, so we don't need to load the URL.
        decisionHandler(.cancel)

        // If we have an inquiry ID we know we have passed verification.
        // You will likely want to transition the view here to show this.
        guard let query = requestUrl.query else {
            return
        }

        print("Process ID and Account ID: " + query)
    }