Full Standard SDK Integration

Prerequisites

You must first set up your mobile environment. To do so, install the SDK into the project following the instructions at Setup Environment. Remember:

High level

This diagram offers a high-level illustration of a straightforward integration. You view a full example of this integration in Github or you can view the recipe.

Step One: Initialize the Incode SDK

The Incode SDK must be initialized before it can be used. The initialization code is different depending on whether your sessions are created in the back end or in the front end.

The following example shows the initialization code for each platform when your sessions are not created in the back end.

Android

public static void IncodeSDKInitialize(Application app) {
  try {

new IncodeWelcome.Builder(app, Constants.API_URL, Constants.API_KEY)
      .setLoggingEnabled(true)
      .build();

// Initialization successful
  } catch (Exception exception) {
    // Initialization error
  }
}

private void setIncodeCommonConfig() {
  CommonConfig commonConfig = new com.incode.welcome_sdk.CommonConfig.Builder()
    .setShowExitConfirmation(true)
    .setShowCloseButton(true)
    .build();

IncodeWelcome.getInstance().setCommonConfig(commonConfig);
}

iOS

func incodeSDKInitialize(api_url: String, api_key: String) {
  IncdOnboardingManager.shared.initIncdOnboarding(url: api_url,
                                                  apiKey: api_key,
                                                  loggingEnabled: true,
                                                  testMode: testMode) { (success, error) in
        print("IncdOnboarding SDK initialization, success: \(success == true), error: \(error?.description ?? "nil")")
        self.dispatchGroup.leave()
    }
}

func setIncodeCommonConfig() {
  IncdOnboardingManager.shared.allowUserToCancel = true
  IncdOnboardingManager.shared.idBackShownAsFrontCheck = true
  IncdOnboardingManager.shared.idFrontShownAsBackCheck = true
}

JavaScript

const IncodeSDKInitialize = (API_URL, API_KEY) => {
    IncodeSdk.initialize({
      testMode: false,
      apiConfig: {
        url: API_URL,
        key: API_KEY,
      },
      waitForTutorials: true,
    })
      .then((_) => {
        startStraightforwardOnboarding();
      })
      .catch((e) => {
        console.error('Incode SDK failed init', e);
      });
};

Flutter

void IncodeSDKInitialize(API_URL,API_KEY) {
    IncodeOnboardingSdk.init(
      apiKey: API_KEY,
      apiUrl: API_URL,
      onError: (String error) {
        print('Incode SDK init failed: $error');
      },
      onSuccess: () {
        onStartOnboarding();
      },
    );
}

Xamarin

// NOTE:
//
// To Initialize the SDK in Xamarin, you need to add the next code into the Native project
// that Xamarin creates.
//
// ANDROID
// **************************************************

using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using Incode.Onboarding;

namespace IncodeOnboardingApplication.Droid
{
    [Activity(Label = "IncodeOnboardingApplication", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

// TODO - 1 - Set environment configuration
            var API_URL = "";
            var API_KEY = "";

IncodeOnboarding.Current.Init(
                url: API_URL,
                apiKey: API_KEY,
                isLoggingEnabled: true,
                isTestMode: false
            );

LoadApplication(new App());
        }
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

If you are creating the session in the back end, the API token needs to end with /0/. This lets the Incode back end know how to manage the request using only the token from the session. The following example shows the initialization code for each platform when your sessions are created in the back end.

Android

public static void IncodeSDKInitialize(Application app) {
  try {
    new IncodeWelcome.Builder(app, Constants.API_URL + "/0/")
      .setLoggingEnabled(true)
      .build();

} catch (Exception exception) {
    // Initialization error
  }
}

IncodeWelcome.getInstance().setCommonConfig(commonConfig);
}

iOS

func incodeSDKInitialize(api_url: String, api_key: String) {
  IncdOnboardingManager.shared.initIncdOnboarding(url: api_url + "/0/",
                                                  loggingEnabled: true,
                                                  testMode: testMode) { (success, error) in
        print("IncdOnboarding SDK initialization, success: \(success == true), error: \(error?.description ?? "nil")")
        self.dispatchGroup.leave()
    }
}

JavaScript

const IncodeSDKInitialize = (API_URL, API_KEY) => {
    IncodeSdk.initialize({
      testMode: false,
      apiConfig: {
        url: API_URL + "/0/",
      },
      waitForTutorials: true,
    })
      .then((_) => {
        startStraightforwardOnboarding();
      })
      .catch((e) => {
        console.error('Incode SDK failed init', e);
      });
};

Flutter

void IncodeSDKInitialize(API_URL,API_KEY) {
    IncodeOnboardingSdk.init(
      apiUrl: API_URL + "/0/",
      onError: (String error) {
        print('Incode SDK init failed: $error');
      },
      onSuccess: () {
        onStartOnboarding();
      },
    );
}

If you are creating the session in the back end, you need to configure the session token to let the SDK save all the information captured during onboarding to that session. You also need to create a way to share that token from your backend to your frontend. This is usually done by an additional API that you need to create. Once the frontend has the token ( SESSION_TOKEN_FROM_BACKEND), you pass it to the SDK.

Step Two: Create Session

A session must be created for data to be captured. You can choose whether sessions are created in the back end or front end. Either way, you need the Configuration ID, also known as the Incode Flow identifier or Flow ID, for your new sessions. If you don't know the Flow ID, open Dashboard > Flows, locate the Flow you want to reference, and click Copy Flow ID in the Actions column. If you have not yet configured the Flow you want to use, see the Getting Started Guide.

Android

private SessionConfig getSimpleSession() {
    SessionConfig sessionConfig = new SessionConfig.Builder()
            .setConfigurationId(Constants.CONFIGURATION_ID)
            .build();

return sessionConfig;
}

iOS

func createSessionConfiguration() -> IncdOnboardingSessionConfiguration {
  return IncdOnboardingSessionConfiguration(regionCode: "ALL",
                                            configurationId: "PASTE__HERE_CONFIGURATION_ID")
}

JavaScript

function getSimpleSession() {
    let sessionConfig: {
      region: 'ALL',
      configurationId: CONFIGURATION_ID,
    };

return sessionConfig;
}

Flutter

OnboardingSessionConfiguration getSimpleSession() {
  // Common configs
  IncodeOnboardingSdk.showCloseButton(allowUserToCancel: true);

// Session config
  OnboardingSessionConfiguration sessionConfig = OnboardingSessionConfiguration(configurationId: CONFIGURATION_ID);

return sessionConfig;
}

Xamarin

// Not possible to do it in Xamarin for now

JavaScript

function startSession() {
  cordova.exec(function(data) {
       // Start the Incode moudles or sections from here
       startOnboardingSection();
       }, function(err) {
        console.log(" startSession Error: "+ err);
         // handle the error by showing some UI or alert.
         callbackError('Nothing to echo.' +err);
     }, "Cplugin", "setupOnboardingSession", [configId,null,null,null]);
}

If you are creating the session in the backend, you need to configure the session token to let the SDK save all the information captured during onboarding to that session. You also need to create a way to share that token from your backend to your frontend. This is usually done by an additional API that you need to create. Once the frontend has the token ( SESSION_TOKEN_FROM_BACKEND), you pass it to the SDK.

Android

private SessionConfig getSimpleSession() {
    SessionConfig sessionConfig = new SessionConfig.Builder()
            .setExternalToken(SESSION_TOKEN_FROM_BACKEND)
            .build();

return sessionConfig;
}

iOS

func createSessionConfiguration() -> IncdOnboardingSessionConfiguration {
  return IncdOnboardingSessionConfiguration(regionCode: "ALL",
                                            token: SESSION_TOKEN_FROM_BACKEND)
}

JavaScript

function getSimpleSession() {
    let sessionConfig: {
      region: 'ALL',
      token: SESSION_TOKEN_FROM_BACKEND,
    };

return sessionConfig;
}

JavaScript

OnboardingSessionConfiguration getSimpleSession() {
  // Common configs
  IncodeOnboardingSdk.showCloseButton(allowUserToCancel: true);

// Session config
  OnboardingSessionConfiguration sessionConfig = OnboardingSessionConfiguration(token: SESSION_TOKEN_FROM_BACKEND);

return sessionConfig;
}

Step Three: Configure User Experience

The default onboarding experience is one in which:

You can customize this user experience as needed. The following example shows the code for configuring the default experience for each platform.

Android

private FlowConfig getStraightforwardFlowConfig() {
    FlowConfig flowConfig = null;
    try {
        flowConfig = new FlowConfig.Builder()
                .addID(new IdScan.Builder()
                        .setIdType(IdScan.IdType.ID)
                        .setShowIdTutorials(true)
                        .setWaitForTutorials(true)
                        .setEnableFrontShownAsBackCheck(true)
                        .setEnableBackShownAsFrontCheck(true)
                        .setIdCategory(IdCategory.FIRST)
                        .build())
                .addProcessId(new ProcessId.Builder()
                        .setIdCategory(IdCategory.FIRST)
                        .build()
                )
                .addSelfieScan(new SelfieScan.Builder()
                        .setShowTutorials(true)
                        .setWaitForTutorials(true)
                        .setMaskCheckEnabled(true)
                        .setLensesCheckEnabled(true)
                        .build()
                )
                .addFaceMatch(new FaceMatch.Builder()
                        .setShowUserExists(false)
                        .build()
                )
                .build();
    } catch (ModuleConfigurationException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

return flowConfig;
}

iOS

func createFlowConfiguration() -> IncdOnboardingFlowConfiguration {
  let flowConfig = IncdOnboardingFlowConfiguration(waitForTutorials: true)
  flowConfig.addIdScan()
  flowConfig.addProcessId()
  flowConfig.addSelfieScan()
  flowConfig.addFaceMatch()
  return flowConfig
}

JavaScript

function getStraightforwardFlowConfig() {
    let flowConfig = [
      { module: 'IdScanFront', showTutorial: true, idType: 'id' },
      { module: 'IdScanBack', showTutorial: true, idType: 'id' },
      { module: 'ProcessId'},
      { module: 'SelfieScan', showTutorial: true, lensesCheck: false },
      { module: 'FaceMatch' },
    ];

return flowConfig;
}

Flutter

OnboardingFlowConfiguration getStraightforwardFlowConfig() {
  OnboardingFlowConfiguration flowConfig = OnboardingFlowConfiguration();

flowConfig.addIdScan(scanStep: ScanStepType.front, idType: IdType.id, showTutorials: true);
  flowConfig.addIdScan(scanStep: ScanStepType.back, idType: IdType.id, showTutorials: true);
  flowConfig.addProcessId();
  flowConfig.addSelfieScan(showTutorials: true);
  flowConfig.addFaceMatch();

return flowConfig;
}

Xamarin

config.AddIdScan(new IdScanParams(showTutorials: true), result => ProcessIdScanCallback(result));
config.AddSelfieScan(new SelfieScanParams(showTutorials: true, lensesCheck: true, maskCheckEnabled:true, brightnessThreshold: null), result => ProcessSelfieScanCallback(result));
config.AddFaceMatch(new FaceMatchParams(), result => ProcessFaceMatchCallback(result));

JavaScript

function startOnboardingSection() {
              cordova.exec(function(winParam) {
                                    console.log("startOnboardingSection Success: ");
                                    finishOnboarding();//user defined
                                    }, function(err) {
                                     console.log("Error: "+ err);
                                     // handle the error by showing some UI or alert.
                                      callbackError('Nothing to echo.' +err);
                                  }, "Cplugin", "startOnboardingSection", [
                                  {"module":"addId","showTutorials":"true","waitForTutorials":"true",
                                    "idCategory":"FIRST","enableBackShownAsFrontCheck":"true",
                                    "enableFrontShownAsBackCheck":"true","autocaptureUXMode":"HOLDSTILL"},
                                  {"module":"addSelfieScan","showTutorials":"true","waitForTutorials":"true",
                                    "maskCheckEnabled":"true","lensesCheckEnabled":"true"},
                                  {"module":"addFaceMatch"}]);
}

Step Four: Implement Callbacks

During the user's journey through your onboarding flow, various callbacks are executed by Incode. You can add custom business logic in these callbacks if needed. However, showing a custom screen between steps is not supported.

Android

private IncodeWelcome.OnboardingListener getStraightforwardOnboardingListener() {
        IncodeWelcome.OnboardingListener onboardingListener = new IncodeWelcome.OnboardingListener() {
            @Override
            public void onOnboardingSessionCreated(String token, String interviewId, String region) {
                super.onOnboardingSessionCreated(token, interviewId, region);

((MainActivity) activity).interviewId = interviewId;
            }

@Override
            public void onIdFrontCompleted(IdScanResult result) {
                super.onIdFrontCompleted(result);

Timber.d("onIdFrontCompleted: %s", result);
            }

@Override
            public void onIdBackCompleted(IdScanResult result) {
                super.onIdBackCompleted(result);

Timber.d("onIdBackCompleted: %s", result);
            }

@Override
            public void onIdProcessed(IdProcessResult result) {
                super.onIdProcessed(result);

Timber.d("onIdProcessed: %s", result);
            }

@Override
            public void onSelfieScanCompleted(SelfieScanResult result) {
                super.onSelfieScanCompleted(result);

Timber.d("onSelfieScanCompleted: %s", result);
            }

@Override
            public void onFaceMatchCompleted(FaceMatchResult result) {
                super.onFaceMatchCompleted(result);

Timber.d("onFaceMatchCompleted: %s", result);

executeFaceMatchValidationCheck(result);
            }

@Override
            public void onSuccess() {
                super.onSuccess();

Timber.d("onSuccess");

fetchUserScores(interviewId);
            }

@Override
            public void onError(Throwable error) {
                super.onError(error);

Timber.d("onError: %s", error);
            }

@Override
            public void onUserCancelled() {
                super.onUserCancelled();

Timber.d("onUserCancelled");
            }
        };

return onboardingListener;
    }

iOS

extension MainViewController: IncdOnboardingDelegate {
    
    func onOnboardingSessionCreated(_ result: OnboardingSessionResult) {
        print("onOnboardingSessionCreated, result: \(result)")
        if result.error != nil {
            let interviewId = result.interviewId
        }
    }

func onIdFrontCompleted(_ result: IdScanResult) {
        print("front IdScanResult: \(result)")
    }

func onIdBackCompleted(_ result: IdScanResult) {
        print("back IdScanResult: \(result)")
    }

func onIdProcessed(_ result: IdProcessResult) {
        print("idProcessResult: \(result)")
    }

func onSelfieScanCompleted(_ result: SelfieScanResult) {
        print("onSelfieScanCompleted, result: \(result)")
    }

func onFaceMatchCompleted(_ result: FaceMatchResult) {
        print("onFaceMatchCompleted, result: \(result)")
    }

func onSuccess() {
        print("onSuccess")

fetchUsetScore()
    }

func onError(_ error: IncdFlowError) {
        print("onError, result: \(error)")
    }

func userCancelledSession() {
        print("userCancelledSession")
    }
}

JavaScript

const setupListeners = ({}) => {
  // returns a callback to unregister your listener, e.g. when your screen is getting unmounted
  IncodeSdk.onSessionCreated((session) => {
    let interviewID = session.interviewId
  });

const complete = IncodeSdk.onStepCompleted;

return [
    complete({
      module: 'IdScanFront',
      listener: (e)  => {
        console.log('IdScanFront result: ', e.result);
      },
    }),
    complete({
      module: 'IdScanBack',
      listener: (e) => {
        console.log('IdScanBack result: ', e.result);
      },
    }),
    complete({
      module: 'ProcessId',
      listener: (e) => {
        console.log('ProcessId result: ', e.result);
      },
    }),
    complete({
      module: 'SelfieScan',
      listener: (e) => {
        console.log('SelfieScan result:', e.result);
      },
    }),
    complete({
      module: 'FaceMatch',
      listener: (e) => {
        console.log('FaceMatch result: ', e.result);
      },
    }),
  ];
};

useEffect(() => {
    const unsubscribers = setupListeners({});
    // return a function unregistering all your listeners
    return () => {
      unsubscribers.forEach((unsubscriber) => unsubscriber());
    };
  }, []);

JavaScript

void onSuccessCallback() {
}

void onErrorCallback(String error) {
}

void onUserCancelledCallback() {
}

void onIdFrontCompletedCallback(IdScanResult result) {
  print("ID Front");
  print(result);
}

void onIdBackCompletedCallback(IdScanResult result) {
  print("ID Back");
  print(result);
}

void onIdProcessedCallback(String result) {
  print("ID Process");
  print(result);
}

void onSelfieScanCompletedCallback(SelfieScanResult result) {
  print("Selfie Scan");
  print(result);
}

void onFaceMatchCompletedCallback(FaceMatchResult result) {
  print("Face Match");
  print(result);
}

JavaScript

private void ProcessIdScanCallback(IdValidationResult result) {
  if (result != null) {
    if (result.Result == ResultCode.Success) {
      Debug.WriteLine("######## Id Scan Completed!");
      Debug.WriteLine($