{"id":24087153,"url":"https://github.com/trusona/trusona-mobile-sdk-android","last_synced_at":"2026-05-16T07:37:07.814Z","repository":{"id":44656081,"uuid":"142207104","full_name":"trusona/trusona-mobile-sdk-android","owner":"trusona","description":"Trusona Mobile SDK for Android","archived":false,"fork":false,"pushed_at":"2022-02-01T20:14:28.000Z","size":465,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-10T03:02:28.367Z","etag":null,"topics":["android","api-21","java-8","sdk"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trusona.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-24T20:02:28.000Z","updated_at":"2022-01-14T21:56:18.000Z","dependencies_parsed_at":"2022-07-24T21:02:18.542Z","dependency_job_id":null,"html_url":"https://github.com/trusona/trusona-mobile-sdk-android","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusona%2Ftrusona-mobile-sdk-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusona%2Ftrusona-mobile-sdk-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusona%2Ftrusona-mobile-sdk-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusona%2Ftrusona-mobile-sdk-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trusona","download_url":"https://codeload.github.com/trusona/trusona-mobile-sdk-android/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240977219,"owners_count":19887617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","api-21","java-8","sdk"],"created_at":"2025-01-10T03:02:35.047Z","updated_at":"2026-05-16T07:37:07.786Z","avatar_url":"https://github.com/trusona.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Trusona Mobile SDK for Android\n\nThe Trusona SDK allows simplified interaction with the Trusona API.\n\n## Table of Contents\n1. [Prerequisites](#prerequisites)\n    1. [Artifactory username and password](#artifactory-username-and-password)\n    1. [Minimum Android Version](#minimum-android-version)\n1. [Required Configuration](#required-configuration)\n    1. [Adding your credentials to `$HOME/.gradle/gradle.properties`](#adding-your-credentials-to-$HOME/.gradle/gradle.properties)\n    1. [Adding the Trusona repository to Gradle](#adding-the-trusona-repository-to-gradle)\n1. [Installation](#installation)\n    1. [Installing as a gradle dependency](#installing-as-a-gradle-dependency)\n    1. [Java 8 Configuration](#java-8-configuration)\n    1. [AndroidX Configuration](#androidx-configuration)\n1. [Creating a Trusona instance](#creating-a-trusona-instance)\n    1. [Device identifier](#device-identifier)\n        1. [Generated Keys](#generated-keys)\n        1. [Requesting a Device Identifier](#requesting-a-device-identifier)\n            1. [Example](#example)\n1. [Scanning TruCodes](#scanning-trucodes)\n    1. [Customizing the scanner UI](#customizing-the-scanner-ui)\n1. [Polling for an IN_PROGRESS Trusonafication](#polling-for-an-in_progress-trusonafication)\n1. [Fetching a single in progress trusonafication and handling it via startTrusonaficationActivity](#fetching-a-single-in-progress-trusonafication-and-handling-it-via-startTrusonaficationActivity)\n1. [Scanning Driver's Licenses](#scanning-drivers-licenses)\n1. [Scanning Passports](#scanning-passports)\n1. [Upgrading to Executive](#upgrading-to-executive)\n1. [Customizing the UI](#customizing-the-ui)\n1. [Handling Deep links](#handling-deep-links)\n\n## Prerequisites\n\n### Artifactory username and password\n\nTrusona uses Artifactory to distribute artifacts associated with the Trusona mobile and server SDKs.\n\nWhen Trusona provisions a developer account, we will create a new user in Artifactory and supply you with a username and password that you will use later on in this guide.\n\n### Minimum Android Version\nThe Trusona SDK requires API level 21 or higher. It also requires at least Android Support Library rev. 27.1.1 and Google Play Services rev. 15.0.1.\n\n## Required Configuration\n\n\n### Adding your credentials to `$HOME/.gradle/gradle.properties`\n\nGradle supports user specific variables which is a convenient way to handle using sensitive data\nin your Gradle scripts without having to check them into your source control system. Create or\nopen the `$HOME/.gradle/gradle.properties` file under your user's home directory and add the following:\n\n```\ntrusonaUsername=\u003cYOUR_TRUSONA_ISSUED_MAVEN_USERNAME\u003e\ntrusonaPassword=\u003cYOUR_TRUSONA_ISSUED_MAVEN_PASSWORD\u003e\n```\n\n### Adding the Trusona repository to Gradle\n\nTo add the private Trusona repository to your project, edit the `build.gradle` file **at the root folder** and add the following:\n\n```groovy\nallprojects {\n    repositories {\n        maven { url = \"https://maven.google.com\" }\n        mavenCentral()\n        mavenLocal()\n        jcenter()\n\n        // the trusona repository\n        maven {\n            credentials {\n                username = trusonaUsername\n                password = trusonaPassword\n            }\n            url = \"https://trusona.jfrog.io/trusona/sdk-releases/\"\n        }\n    }\n}\n```\n\n\n## Installation\n\nThe Trusona SDK should be declared as a dependency in your Gradle project.\n\n### Installing as a gradle dependency\n\n\u003e Note: This method requires access to the private Trusona SDK Artifactory repository\n\n1. Ensure that your `~/.gradle.properties` file contains your supplied Artifactory credentials\n1. Define the SDK version you wish to use and add the `api` dependency to your Gradle project.\n\n```gradle\ndependencies {\n  // other dependencies\n  api \"com.trusona.android:mobile-sdk:11.3.2\"\n\n  // the following is only required if you will be using the Trusona Passport SDK\n  //api \"com.trusona.android:passport-sdk:8.0.3\"\n}\n```\n\n### Java 8 Configuration\n\nThe SDK requires Java 8 compatibility. Be sure to have the following configuration within the `android` block of your project's `build.gradle` file:\n\n```gradle\ncompileOptions {\n  sourceCompatibility 1.8\n  targetCompatibility 1.8\n}\n```\n\n### AndroidX Configuration\n\nThe SDK has dependencies on the latest [AndroidX](https://developer.android.com/jetpack/androidx) libraries.\n\nFor normal function and compatibility with legacy support libraries, add the following configuration to your project's `gradle.properties` file:\n\n```\nandroid.enableJetifier=true\nandroid.useAndroidX=true\n```\n\n## Creating a Trusona instance\n\nTo create an instance of `Trusona` for making API calls, use the provided constructor.\n\n```java\nTrusona trusona = new Trusona();\n```\n\nThe Trusona SDKs have infrastructure in place to serve the US and European regions, with the US being the default one. Unless otherwise noted, you will not need to configure Trusona to use a specific region. If you have been provisioned in the European region, you will need to point the SDK to use that region. To achieve this, you’ll need to specify the `EU` value from the `Region` enum when building a `Trusona` instance.\n\n```java\n// Use this to connect to the European region\nTrusona trusona = new Trusona(Region.EU);     \n```\n\nIf you have deployed your own infrastructure, you can customize the SDK to use it by providing the base url that points to it, as shown below:\n\n```java\nCustomBaseUrl customBaseUrl = new CustomBaseUrl(\"https://my.custom.base.url.net\");\nTrusona trusona = new Trusona(customBaseUrl);\n```\n\nNote that if the url is incorrectly formatted, the sdk will default to using the US infrastructure.\n\n### Device Identifier\n\nA device identifier is required to interact with some of the Trusona APIs. To acquire one, simply\nmake a request to the Trusona API via the `getDeviceIdentifier` method and this will create or update a\ndevice in the Trusona servers. Internally, a set of cryptographic keys will be generated and stored\nin the Android Keystore.\n\n\u003e **NOTE** The TrusonaSDK will not work on a device running an API lower than 21.\n\n#### Generated Keys\n\nThe Trusona SDK attempts to generate three types of keys:\n\n* **Device Key** - The Device Key is always generated and does not require User Presence. Using this key for signing operations will not prompt the user for any interaction with the device.\n* **User Lock Screen Auth Key** - The User Lock Screen Auth Key is generated when the user has a pin, pattern or password set. Using this key for signing operations (e.g. during a Trusonafication) will prompt the user to enter their pin, pattern or password.\n* **User Fingerprint Auth Key** - The User Fingerprint Auth Key is generated when the user has at least one fingerprint enrolled on the device. Using this key for signing operations (e.g. during a Trusonafication) will prompt the user to enter their fingerprint.\n\nDuring signing, the SDK will give precedence to the `User Fingerprint Auth Key` but it also provides a mechanism to fall back to the `User Lock Screen Auth Key`, should the device owner be unable to present their enrolled fingerprint.\n\n#### Requesting a Device Identifier\n\nRequesting a device identifier is an asynchronous operation which, once completed, will provide an instance\nof `DeviceIdentifierResponse`. This response will contain the device's request status and a device identifier\nif one was generated.\n\nThe various results of a request to `getDeviceIdentifier` are:\n\n#### Successful results\n\n|        Result           |                                                                       Description                                                                        |  Returns Identifier?  |\n| :--------------------   | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------: |\n| `NEW_DEVICE`            | Indicates that a new device was successfully created.                                                                                                    |           Yes         |\n| `INACTIVE_DEVICE`       | Indicates that the device was already created, but is inactive.                                                                                          |           Yes         |\n| `ACTIVE_DEVICE`         | Indicates that the device was already created, and is active.                                                                                            |           Yes         |\n\n#### Failed results\n\n|        Result           |                                                                       Description                                                                        |  Returns Identifier?  |\n| :--------------------   | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------: |\n| `INVALID_DEVICE`        | Indicates that the request to create the device failed because the server determined the device to be invalid.                                           |           No          |\n| `SERVER_ERROR`          | Indicates that the request to create the device failed because the server encountered an error.                                                          |           No          |\n| `UNKNOWN`               | Indicates that an unknown error occurred.                                                                                                                |           No          |\n\n#### Example\n\nThe following code demonstrates how to acquire a device identifier.\n\n```java\n// 1\nDeviceIdentifierRequester deviceIdentifierRequester = new DeviceIdentifierRequester() {\n    @Override\n    public void onDeviceIdentifier(@NonNull DeviceIdentifierResponse deviceIdentifierResponse) {\n        switch (deviceIdentifierResponse.getDeviceStatus()) {\n\n            case ACTIVE_DEVICE:\n                // A device identifier is available and the device is ready to perform trusonafications.\n                break;\n\n            case INACTIVE_DEVICE:\n            case NEW_DEVICE:\n                // A device identifier is available in these scenarios.\n                break;\n\n            case INVALID_DEVICE:\n            case SERVER_ERROR:\n            case UNKNOWN:\n                // A device identifier is not available in these scenarios.\n                break;\n        }\n    }\n};\n\n//2\ntrusona.getDeviceIdentifier(context, deviceIdentifierRequester);\n\n```\n\n1. Implement the `DeviceIdentifierRequester` interface that will receive an instance of `DeviceIdentifierResponse`.\nThe latter will contain the device's status, the `device identifier` and an optional `String` that contains a signed JWT containing the device identifier in the `sub` field. This JWT can be verified against the JWK set at https://api.trusona.net/jwks to verify its authenticity.\n2. Invoke the Trusona API passing in a reference to a context and your implementation of `DeviceIdentifierRequester`.\n\n\n\u003e **NOTE** Do not store and reuse your device identifier, as it is subject to change. Always call the\n`getDeviceIdentifier` method whenever you need the most current device identifier.\n\n\n### Scanning TruCodes\n\nTruCodes are a mechanism used to identify the user that is attempting to log into a resource protected by trusona.\n\nThe Trusona SDk provides a Scanner that will recognize TruCodes and create a Trusonafication whenever one of them is\nscanned.\n\nThe following example illustrates how to use the TruCode Scanner by loading it as a child `Fragment` of another\n`Fragment` that's already in the foreground:\n\n```java\n// 1\nTruCodeHandler truCodeHandler = new TruCodeHandler() {\n  \n  @Override\n  public void onTrusonaficationCreated() {\n    // The TruCode was successfully scanned. You may want to start monitoring for pending\n    // trusonafications at this point if you haven't done so yet.\n  }\n\n  @Override\n  public void onError(String payload) {\n    // There was an error while processing the TruCode\n  }\n\n  @NonNull\n  @Override\n  public Integer fragmentContainerId() {\n    // Update this method to return the id of the ViewGroup container into which the Trusona\n    // SDK will display the TruCode Scanner. This ID must be present in the layout of the fragment\n    // that's in the foreground and that's passed in to the loadTruCodeAsChildFragment() method.\n    // i.e.: R.id.tru_code_scanner_container.\n    return null;\n  }\n};\n\n// 2\nIdentifierProvider identifierProvider = new IdentifierProvider() {\n  @Override\n  public String identifier() {\n    // Return your device's identifier\n    return null;\n  }\n};\n\n// 3\ntrusona.loadTruCodeAsChildFragment(myFragment, truCodeHandler, identifierProvider);\n```\n\n1. Implement the `TruCodeHandler` interface, which will be notified when the Trucode has been scanned.\n2. Implement the `IdentifierProvider` to return the device's identifier\n3. Invoke the Trusona API passing in the implemented interfaces and a reference to the `Fragment` where the TruCode Scanner should be displayed. This API call should be done once the `Fragment` passed as a parameter\nhas been attached to its corresponding activity and is visible, for example, during it's `onViewCreated` method.\n\nAlternatively, if you'd like to load the TruCode scanner in a layout that is not part of a `Fragment`, the \n`getTruCodeFragment` method provides a `Fragment` reference that can be loaded using an Activity's \n`SupportFragmentManager`.\n\n#### Customizing the scanner UI\n\nIn order to customize the scanner UI, you can modify the contents of the layout xml file inflated by the `myFragment` instance passed in to the `trusona.loadTruCodeAsChildFragment(myFragment, truCodeHandler, identifierProvider)` method. \nYou'll want to arrange your custom views in such a way that they will be placed on top of the scanner's viewfinder. \n\nThe following xml layout file demonstrates how to do this:\n\n```xml\n\u003cFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n\n    \u003c!-- The id of this FrameLayout should match the one returned by your implementation of  --\u003e\n    \u003c!-- TrucodeHandler's `fragmentContainerId()` method. --\u003e\n    \u003cFrameLayout\n        android:id=\"@+id/tru_code_scanner_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" /\u003e\n\n    \u003c!-- TODO: Place any custom views you'd like to add below this line, so that they're laid --\u003e\n    \u003c!-- on top of the scanner --\u003e\n\n\u003c/FrameLayout\u003e\n```\n\nUsing this strategy, you can add any custom views you'd like on top of the scanner and you can set click \nlisteners or modify them as you would typically do: By getting a reference to them during `myFragment`'s\n`onCreateView` lifecycle method.\n\n### Polling for an IN_PROGRESS Trusonafication\n\nA Trusonafication occurs when a user attempts to access a protected resource, and the user is allowed\nto accept or deny the action. When a Trusonafication is received, the app needs to respond to confirm\nthe user's identity. Depending on how the Trusonafication was created, this may involve a visual prompt\nrequiring the user to accept and/or provide the credentials used to unlock the device.\n\nPolling for in progress trusonafications should happen only when your application is in the foreground.\nTypically you'll want to start the polling process in your `Activity`'s `onResume` or `onCreate` lifecycle\ncallback. The SDK will automatically stop the polling process for you during the `onStop` lifecycle \ncallback, however, if you need to stop polling at a particular point in time, you may use the `stop()`\nmethod of the `PollerStopper` object returned by the `startPolling` method.\n\nA call to the `startPolling` method requires an instance of `AppCompatActivity` in order to start a new\nSDK controlled Activity when a Trusonafication is received. The latter is invoked via the `startActivityForResult`\nmethod, so the calling `AppCompatActivity` must implement `onActivityResult` in order to receive the\noutcome of the processed `Trusonafication`.\n\n#### Example\n\n```java\npublic class MyActivity extends AppCompatActivity {\n\n  private Trusona trusona = new Trusona();\n\n  @Override\n  protected void onCreate(Bundle savedInstanceState) {\n    super.onCreate(savedInstanceState);\n    // 1\n    trusona.startPolling(this);\n  }\n\n  // 2\n  @Override\n  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n    super.onActivityResult(requestCode, resultCode, data);\n    if (requestCode == TrusonaficationActivity.TRUSONAFICATION_ACTIVITY_REQUEST_CODE \u0026\u0026 resultCode == RESULT_OK \u0026\u0026 data != null) {\n\n      // 3\n      Trusonafication trusonafication;\n      try {\n        trusonafication = TrusonaficationParser.getFromIntent(data);\n      }\n      catch (IllegalArgumentException e) {\n        trusonafication = null;\n        //Trusonafication not present in intent data\n      }\n\n      // 4\n      /* This Throwable will be returned if something goes wrong while processing a trusonafication. */\n      Throwable error = (Throwable) data.getSerializableExtra(TrusonaficationActivity.ERROR_KEY);\n\n      if (trusonafication != null \u0026\u0026 error == null) {\n        // 5\n        handleTrusonaficationResult(trusonafication);\n      }\n      else {\n        // 6\n        handleError(error);\n      }\n    }\n  }\n\n  private void handleError(Throwable error) {\n    // Some of the possible exceptions that can be received are:\n    if (error instanceof RequiredIdentityDocumentException) {\n        /* Used when a trusonafication required that the user\n         presents their Identity Document but they have not registered one to their account yet */\n    }\n    else if (error instanceof InvalidIdentityDocumentException) {\n        /* Used when the scanned Identity document is not in\n         AAMVA format or it was not accepted by the trusona servers. */\n    }\n    else if (error instanceof UnavailableDeviceSecurityException) {\n      /* Used when the trusonafication requires that the device has enabled a pin/pattern/password/biometric\n      but it hasn't. */\n    }\n    else {\n      //Unexpected type of exception\n    }\n  }\n\n  private void handleTrusonaficationResult(Trusonafication trusonafication) {\n    switch (trusonafication.getStatus()) {\n\n      case ACCEPTED:\n        // The trusonafication was successfully accepted by the user\n        break;\n\n      case REJECTED:\n        // The trusonafication was successfully rejected by the user\n        break;\n\n      case FAILED:\n        // The user attempted to accept or reject the trusonafication but an error occurred\n        break;\n\n      case EXPIRED:\n        // The user did not accept or reject the trusonafication during it's validity period,\n        // which by default is 2 minutes.\n        break;\n\n      case CANCELED:\n        // The trusonafication was cancelled\n        break;\n\n      case IN_PROGRESS:\n        // The trusonafication is still in progress. This means the user backed out of the trusonafication\n        // process, typically by sending the app to the background via the device's home button.\n        break;\n\n      default:\n        break;\n    }\n  }\n}\n```\n\n1. Call `trusona.startPolling(this)` during the Activity's `onCreate` method.\n2. Override `onActivityResult` so you can receive the trusonafication result passed back by the SDK.\n3. Use the `TrusonaficationParser` to acquire the processed `Trusonafication` from the passed in `Intent`.\n4. Query the passed in `Intent` for any errors that may have been thrown during the trusonafication process.\n5. If no errors were thrown, handle the trusonafication result by examining its `TrusonaficationStatus`.\n6. If an error was thrown, handle accordingly.\n\n### Fetching a single in progress trusonafication and handling it via startTrusonaficationActivity\n\nIf you'd like to acquire a single in-progress trusonafication, you can do so by calling the \n`fetchNexTrusonafication(TrusonaficationListener)` method of the `Trusona` class.\n\nBeing an asynchronous method, this requires that you pass in an implementation of the `TrusonaficationListener`\ninterface, which will provide you with the callbacks to determine the right course of action depending on \nwhether a trusonafication was found or not.\n\nIn case a trusonafication is found, you may want to process it via one of the variants of the `startTrusonaficationActivity`\nmethod.\n\n```java\n// 1\nTrusonaficationListener trusonaficationListener = new TrusonaficationListener() {\n    @Override\n    public void onTrusonafication(Trusonafication trusonafication) {\n        // This callback will execute if an in-progress trusonafication is found.\n        // You may want examine the trusonafication or request that the SDK\n        // processes it by calling:\n        // trusona.startTrusonaficationActivity(appCompatActivity, trusonafication);\n    }\n\n    @Override\n    public void onErrorFetchingTrusonafication(Throwable throwable) {\n        // This callback will execute if no trusonafication was found or\n        // if an error occured. You can examine the throwable parameter\n        // to determine which was the case.\n    }\n};\n\n// 2\ntrusona.fetchNexTrusonafication(trusonaficationListener);\n```\n\n1. Implement the `TrusonaficationListener` interface.\n2. Using a previously instantiated `Trusona` object, call `fetchNexTrusonafication`, passing in\nyour implementation of the `TrusonaficationListener` interface.\n\n\n### Scanning Driver's Licenses\n\nThe Trusona SDK provides a user interface that can be shown to prompt the user to scan the barcode on a US/Canadian driver's license. The SDK will execute a callback in the app upon successful scanning and provide the parsed contents of the barcode. In the case of failure, another callback will be called, which should handle the failure in a way that makes sense in the app.\n\nNote: Scanning a driver's license as part of accepting a Trusonafication is handled automatically by the SDK. Use the following method only if you require to examine the contents\nof a driver's license as part of the business logic in your application.\n\n```java\n// 1\nPDF417ScanHandler pdf417ScanHandler = new PDF417ScanHandler() {\n\t\n    @Override\n    public void onSuccess(@NonNull DriversLicenseScanResult result) {\n    \t// examine license properties as necessary\n    \tAAMVADriversLicense license = result.getDriversLicense();\n    \t\n    \t// examine scanning event's metadata. This metadata is subject to change. Additionally, \n    \t// all properties may not be available for all scan results.\n\t// Current available properties are:\n\t// x - result of division of the x/y point of the top left corner\n\t// y - result of division of the x/y point of the top right corner\n\t// h - result of division of the x/y point of the bottom left corner\n\t// w - result of division of the x/y point of the bottom right corner\n\t// t - value returned by System.nanoTime()\n\t//\n    \tMap\u003cString, ?\u003e metadata = result.getMetadata();    \n    }\n\t\n    @NonNull\n    @Override\n    public Integer fragmentContainerId() {\n        // Return the ID of the ViewGroup in which the SDK will attempt to load the Driver\n        // License scanner. This ID must be present in the layout of the Fragment that's passed\n        // in as a parameter to the scanDriversLicense method, and the Fragment must have been\n        // brought into the foreground and be ready to host the Driver License scanner.\n        // i.e.: R.id.my_fragment_container.\n        return 0;\n    }\n\t\n    @Override\n    public void onDocumentError(Throwable throwable) {\n    \t// handle error case due to invalid document being scanned\n    }\n};\n\n// 2\ntrusona.scanDriversLicense(fragment, pdf417ScanHandler);\n```\n\n1. Implement the `PDF417ScanHandler` interface.\n2. Using a previously instantiated `Trusona` object, call `scanDriversLicense`, passing a reference of the fragment into which the Driver License scanner will be inflated and the instance of the implemented `PDF417ScanHandler`.\n\n\n### Scanning Passports\n\nThe Trusona SDK provides a user interface that can be shown to prompt the user to scan the MRZ data on a passport. The SDK will call a callback in the app upon successful scanning and provide the parsed contents of the passport. In the case of failure, another callback will be called, which should handle the failure in a way that makes sense in the app. \n\n```java\n// 1\nPassportScanHandler passportScanHandler = new PassportScanHandler() {\n    \n    @Override\n    public void passportScanned(PassportScanResult passportScanResult) {\n        // examine license properties as necessary\n        Passport passport = passportScanResult.getPassport();\n        // examine metadata properties as necessary\n        Map\u003cString, Object\u003e metadata = passportScanResult.getMetadata();\n    }\n\n    @Override\n    public void passportScanCanceled() {\n        // Handle what happens when the user taps the Cancel button.\n    }\n\n    @NonNull\n    @Override\n    public Integer fragmentContainerId() {\n        // Return the ID of the ViewGroup in which the SDK will attempt to load the Passport\n        // scanner. This ID must be present in the layout of the Activity that's passed\n        // in as a parameter to the getPassportScanner method, and the Activity must have been\n        // brought into the foreground and be ready to host the Passport scanner.\n        // i.e.: R.id.my_passport_scanner_container.\n        return 0;\n    }\n};\n\n// 2\ntrusona.getPassportScanner(activity, passportScanHandler);\n```\n\n1. Implement the `PassportScanHandler` interface.\n2. Using a previously instantiated `Trusona` object, call `getPassportScanner`, passing a reference of the activity into which the Passport scanner will be inflated and the instance of the implemented `PassportScanHandler`.\n\n### Upgrading to Executive\n\nUsers can be authenticated at the Executive level if they register a driver's license with their account. Before a user can be authenticated with Executive, they must associate a driver's license. The SDK provides a callback interface to perform this step. \n\nBefore doing the upgrade, it is important to make sure the device identifier of the running app has been bound to an account.\n\nThe following code snippet illustrates the required step:\n\n```java\n    \n// 1    \nPDF417UpgradeHandler pdf417UpgradeHandler = new PDF417UpgradeHandler() {\n\n    @Override\n    public void onSuccess(@NonNull IdentityDocument\u003cDriversLicenseScanResult\u003e identityDocument) {\n        // This method will be called when the user was succesfully upgraded, which means\n        // now you  can authenticate them at Executive level.\n        // You may examine the returned IdentityDocument instance as necessary and get a\n        // DriversLicenseScanResult instance to examine via the following method:\n        DriversLicenseScanResult driversLicenseScanResult = identityDocument.getDocument();\n    }\n\n    @NonNull\n    @Override\n    public Integer fragmentContainerId() {\n   \t    // Return the ID of the ViewGroup in which the SDK will attempt to load the Driver\n        // License scanner. This ID must be present in the layout of the Fragment that's passed\n        // in as a parameter to the upgradeToExecutive method, and the Fragment must have been\n        // brought into the foreground and ready to host the Driver License scanner.\n        // i.e.: R.id.my_fragment_container.\n   \t     return 0;\n    }\n\n    @Override\n    public void onDocumentError(Throwable throwable) {\n    \t// handle error case due to invalid document being scanned\n    }\n};\n\n// 2\ntrusona.upgradeToExecutive(fragment, pdf417RegisterHandler);\n```\n\n1. Implement the `PDF417UpgradeHandler` interface.\n2. Using a previously instantiated `Trusona` object, call `upgradeToExecutive`, passing a reference of the fragment into which the Driver License scanner will be inflated and the instance of the implemented `PDF417RegisterHandler`.\n\n### Customizing the UI\nDuring the Trusonafication process, the user will be presented with several steps of confirmation, depending on the level of verification requested in the Trusonafication. These steps may include:\n\n- A visual prompt that gives the user the choice of accepting or rejecting the Trusonafication\n- An operating system authentication (e.g. Fingerprint, Pattern, PIN)\n- Scanning of driver's license\n\nThe prompt and scanning screens can be customized by passing an instance of the `TrusonaficationUICustomizations` interface to the variants of the \n`startPolling` or `startTrusonaficationActivity` methods that receive one as a parameter. If you don't pass in a `TrusonaficationUICustomizations`\nimplementation, then a default dialog and scanner UI will be used.\n\nThe `TrusonaficationUICustomizations` interface has five methods:\n   - `boolean usesCustomDialog()`: Set the return value to true if you'd like to provide a custom prompt/dialog.\n   - `Dialog trusonaficationDialog(Context context, Trusonafication trusonafication)`: If you set the return value of `usesCustomDialog()`\n   to true, then you will need to create and return your custom prompt in this method. Otherwise, you can return null.\n   - `boolean usesCustomDLScanner()`: Set the return value to true if you'd like to provide a custom scanner UI.\n   - `Fragment getCustomDLScanner(Trusonafication trusonafication)`: If you set the return value of `usesCustomDLScanner()`\n   to true, then this method must return an instance of the fragment you'd like to host the scanner in. Otherwise, you can return null.\n   - `Integer getDLScannerContainerId()`: If you set the return value of `usesCustomDLScanner()` to true, then this method must return\n   the `id` of the container in which you want to host the scanner. This `id` has to be defined in the `XML layout` used by the `Fragment`\n   returned by the `getCustomDLScanner(Trusonafication trusonafication)` method. You may return null if you're not using a custom\n   Driver License Scanner.\n\nIt's important to note that `Activities` nor `Fragments` should implement the `TrusonaficationUICustomizations` interface, as the SDK will\nmaintain a reference to it while it's own `Activity` handles the `Trusonafication` flow.\n\n#### Example\n\n```java\n// 1\nTrusonaficationUICustomizations trusonaficationUICustomizations = new TrusonaficationUICustomizations() {\n  \n    @Override\n    public boolean usesCustomDialog() {\n        // Update the return value to indicate whether you'd like to use a custom prompt dialog or not\n        return true;\n    }\n\n    @Override\n    public Dialog trusonaficationDialog(Context context, Trusonafication trusonafication) {\n        // In order to customize the UI used to prompt users to accept or reject \n        // trusonafications, you can return a Dialog that inflates the xml layout \n        // you'd like to use.\n        //\n        // You may customize the views in your Dialog by acquiring a reference to them via the \n        // dialog.findViewById() method and then applying any changes you see fit, like adding\n        // onCLickListeners, applying spans to TextViews, etc.\n        //\n        // When using a custom Dialog, the layout it inflates must contain the following views so\n        // that the sdk can properly process the accept and reject actions of the user:\n        //\n        // * A View with the id `trusonafication_accept_button`\n        // * A view with the id `trusonafication_reject_button`\n        //\n        // The following code returns a full screen dialog that uses the my_trusonafication_layout\n        // xml file: \n\n        Dialog dialog = new Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen);\n        \n        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);\n        dialog.setContentView(R.layout.my_trusonafication_layout);\n\n        // Note: Do not call the show method of the dialog instance. The SDK will do that\n        // at the appropriate moment. Also, if usesCustomDLScanner() returns false, this \n        // method may return null.\n        return dialog; \n    }\n\n    @Override\n    public boolean usesCustomDLScanner() {\n        // Update the return value to indicate whether you'd like to use a custom Driver License Scanner or not\n        return true;\n    }\n\n    @Override\n    Fragment getCustomDLScanner(Trusonafication trusonafication) {\n        // Update this method to return an instance of the Fragment onto which you want to \n        // load the Driver License Scanner or null if your application does not require\n        // Driver License scanning. The Fragment must be loaded by the FragmentManager\n        // before being returned.\n        //\n        // You may inspect the IN_PROGRESS Trusonafication which is passed  as a parameter and \n        // perform any UI updates necessary.\n        //\n        // Note: If usesCustomDLScanner() returns false, this method may return null.\n        //\n        // Sample implementation:\n        return MyFragment.newInstance();\n    }\n\n    @IdRes\n    @Override\n    public Integer getDLScannerContainerId() {\n        // Update this method to return the id of the ViewGroup container into which the Trusona \n        // SDK will display a Driver License Scanner if a Trusonafication requires it. This ID must \n        // be present in the layout of the Fragment returned by the `getCustomDLScanner` method implementation in\n        // this class. Alternatively, this can be null if your application does not require identity\n        // document scanning.\n        //\n        // Note: If usesCustomDLScanner() returns false, this method may return null.\n        // \n        // Sample implementation:\n        return R.id.my_fragment_container;\n    }\n};\n\n// 2\ntrusona.startPolling(appCompatActivity, trusonaficationUICustomizations);\n```\n\n1. Implement the `TrusonaficationUICustomizations` interface. The layout used by the Dialog created in the \n`trusonaficationDialog(Context context, Trusonafication trusonafication)` method can be styled in any way but it must contain\nthe following views to be properly rendered and to allow the sdk to process accepting and rejecting the trusonafication:\n* A View with the id `trusonafication_accept_button`\n* A view with the id `trusonafication_reject_button`\n\n2. Using a previously instantiated `Trusona` object, call `startPolling` (or `startTrusonaficationActivity`), passing \nan instance of the implemented `TrusonaficationUICustomizations`. Usually, you would do this in your `Activity`'s `onResume` \nor `onCreate` method.\n\n#### Custom Trusonafication metadata\nWhen creating a Trusonafication from one of the server SDKs, it is possible to include a set of custom fields on the Trusonafication. \nThese custom fields are made available in your implementation of `TrusonaficationUICustomizations` when the `trusonaDialog(Context context, Trusonafication trusonafication)` \nand `getCustomDLScanner(Trusonafication trusonafication)` callback methods are called and a Trusonafication is passed in as a parameter to them. \nThe custom data will be available in the `customFields` property of the Trusonafication. By inspecting the custom data in these fields, the \ndialog behavior can be customized or the data can be shown in the dialog UI.\n\n### Handling Deep links\n\nYour mobile application needs to be configured to handle deep links so that it can receive the data passed by the Trusona web SDKs\nto the Trusona mobile SDKs. Depending on your minimum supported Android version, this may mean you'll need to configure App links and\nintent filters for incoming links as well. For more information on how to do this, take a look at the official Android Developers documentation [here](https://developer.android.com/studio/write/app-link-indexing.html) and [here](https://developer.android.com/training/app-links/deep-linking.html).\n\nWhen deeplinking, Trusona will redirect users to your application using this url:\n\n`\u003cscheme\u003e://\u003chandle\u003e.applaunchexpress.com/trucode?payload=XXXXXXXXXXXXXXXX`\n\nThe `scheme` will depend on whether you are using App links or a custom scheme. The former will use `https` and the later a\nscheme of your choice. The `handle` will be provided by Trusona and is unique to your application.\n\nOnce one of your Activities has been set up to handle deep links, it will need to implement the following steps:\n\n```java\n\n//1 \nTruCodeHandler deepLinkTruCodeHandler = new TruCodeHandler() {\n\n    @Override\n    public void onTruCode(boolean success) {\n        if(success) {\n            // the deeplink trusonafication was successfully accepted and validated.\n        }\n        else {\n            // There was an error while processing the deeplink trusonafication.\n        }\n    }\n\n    @Nullable\n    @Override\n    public Integer fragmentContainerId() {\n        // Update this method to return the id of the ViewGroup container in which the accept / reject \n        // prompt will be loaded. This ID must be present in the layout of the fragment passed to the `handleTruCodeDeepLink`\n        // method.\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public Integer acceptRejectLayoutId() {\n        // Update this method to return the id of the layout that will be used to prompt users\n        // to accept or reject trusonafications. Alternatively, return null to use the default OS \n        // alert dialog.\n        return null;\n    }\n};\n\n// 2\n@Override\nprotected void onCreate(Bundle bundle) {\n    super.onCreate(bundle);\n    // Your code goes here\n\n    // 2.1 Load the fragment that will host the accept / reject prompt.\n\n    // 2.2\n    trusona.handleTruCodeDeepLink(fragment, deepLinkTruCodeHandler, getIntent().getData());\n}\n\n@Override\nprotected void onStop() {\n    super.onStop();\n    // Your code goes here\n    // 3\n    trusona.stopPendingTrusonaficationsMonitor();\n}\n```\n\n1. Provide an implementation of the `TruCodeHandler` interface.\n2. Update your activity's `onCreate` method to:\n  * Load the fragment that will host the accept / reject prompt.\n  * Use an existing instance of the Trusona class to call `handleTruCodeDeepLink` passing in a reference to the fragment loaded in the previous step, the `TruCodeHandler` implementation from step 1, and the deep link payload acquired by calling `getIntent().getData()`.\n3. Update your activity's `onStop` method to call `stopPendingTrusonaficationsMonitor`.\n\n### Need additional help?\n\nContact us at engineering@trusona.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrusona%2Ftrusona-mobile-sdk-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrusona%2Ftrusona-mobile-sdk-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrusona%2Ftrusona-mobile-sdk-android/lists"}