The Trusona SDK allows simplified interaction with the Trusona API.
- Prerequisites
- Required Configuration
- Installation
- Creating a Trusona instance
- Scanning TruCodes
- Polling for an IN_PROGRESS Trusonafication
- Fetching a single in progress trusonafication and handling it via startTrusonaficationActivity
- Scanning Driver's Licenses
- Scanning Passports
- Upgrading to Executive
- Customizing the UI
- Handling Deep links
Trusona uses Artifactory to distribute artifacts associated with the Trusona mobile and server SDKs.
When 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.
The 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.
Gradle supports user specific variables which is a convenient way to handle using sensitive data
in your Gradle scripts without having to check them into your source control system. Create or
open the $HOME/.gradle/gradle.properties
file under your user's home directory and add the following:
trusonaUsername=<YOUR_TRUSONA_ISSUED_MAVEN_USERNAME>
trusonaPassword=<YOUR_TRUSONA_ISSUED_MAVEN_PASSWORD>
To add the private Trusona repository to your project, edit the build.gradle
file at the root folder and add the following:
allprojects {
repositories {
maven { url = "https://maven.google.com" }
mavenCentral()
mavenLocal()
jcenter()
// the trusona repository
maven {
credentials {
username = trusonaUsername
password = trusonaPassword
}
url = "https://trusona.jfrog.io/trusona/sdk-releases/"
}
}
}
The Trusona SDK should be declared as a dependency in your Gradle project.
Note: This method requires access to the private Trusona SDK Artifactory repository
- Ensure that your
~/.gradle.properties
file contains your supplied Artifactory credentials - Define the SDK version you wish to use and add the
api
dependency to your Gradle project.
dependencies {
// other dependencies
api "com.trusona.android:mobile-sdk:11.3.2"
// the following is only required if you will be using the Trusona Passport SDK
//api "com.trusona.android:passport-sdk:8.0.3"
}
The SDK requires Java 8 compatibility. Be sure to have the following configuration within the android
block of your project's build.gradle
file:
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
The SDK has dependencies on the latest AndroidX libraries.
For normal function and compatibility with legacy support libraries, add the following configuration to your project's gradle.properties
file:
android.enableJetifier=true
android.useAndroidX=true
To create an instance of Trusona
for making API calls, use the provided constructor.
Trusona trusona = new Trusona();
The 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.
// Use this to connect to the European region
Trusona trusona = new Trusona(Region.EU);
If 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:
CustomBaseUrl customBaseUrl = new CustomBaseUrl("https://my.custom.base.url.net");
Trusona trusona = new Trusona(customBaseUrl);
Note that if the url is incorrectly formatted, the sdk will default to using the US infrastructure.
A device identifier is required to interact with some of the Trusona APIs. To acquire one, simply
make a request to the Trusona API via the getDeviceIdentifier
method and this will create or update a
device in the Trusona servers. Internally, a set of cryptographic keys will be generated and stored
in the Android Keystore.
NOTE The TrusonaSDK will not work on a device running an API lower than 21.
The Trusona SDK attempts to generate three types of keys:
- 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.
- 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.
- 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.
During 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.
Requesting a device identifier is an asynchronous operation which, once completed, will provide an instance
of DeviceIdentifierResponse
. This response will contain the device's request status and a device identifier
if one was generated.
The various results of a request to getDeviceIdentifier
are:
Result | Description | Returns Identifier? |
---|---|---|
NEW_DEVICE |
Indicates that a new device was successfully created. | Yes |
INACTIVE_DEVICE |
Indicates that the device was already created, but is inactive. | Yes |
ACTIVE_DEVICE |
Indicates that the device was already created, and is active. | Yes |
Result | Description | Returns Identifier? |
---|---|---|
INVALID_DEVICE |
Indicates that the request to create the device failed because the server determined the device to be invalid. | No |
SERVER_ERROR |
Indicates that the request to create the device failed because the server encountered an error. | No |
UNKNOWN |
Indicates that an unknown error occurred. | No |
The following code demonstrates how to acquire a device identifier.
// 1
DeviceIdentifierRequester deviceIdentifierRequester = new DeviceIdentifierRequester() {
@Override
public void onDeviceIdentifier(@NonNull DeviceIdentifierResponse deviceIdentifierResponse) {
switch (deviceIdentifierResponse.getDeviceStatus()) {
case ACTIVE_DEVICE:
// A device identifier is available and the device is ready to perform trusonafications.
break;
case INACTIVE_DEVICE:
case NEW_DEVICE:
// A device identifier is available in these scenarios.
break;
case INVALID_DEVICE:
case SERVER_ERROR:
case UNKNOWN:
// A device identifier is not available in these scenarios.
break;
}
}
};
//2
trusona.getDeviceIdentifier(context, deviceIdentifierRequester);
- Implement the
DeviceIdentifierRequester
interface that will receive an instance ofDeviceIdentifierResponse
. The latter will contain the device's status, thedevice identifier
and an optionalString
that contains a signed JWT containing the device identifier in thesub
field. This JWT can be verified against the JWK set at https://api.trusona.net/jwks to verify its authenticity. - Invoke the Trusona API passing in a reference to a context and your implementation of
DeviceIdentifierRequester
.
NOTE Do not store and reuse your device identifier, as it is subject to change. Always call the
getDeviceIdentifier
method whenever you need the most current device identifier.
TruCodes are a mechanism used to identify the user that is attempting to log into a resource protected by trusona.
The Trusona SDk provides a Scanner that will recognize TruCodes and create a Trusonafication whenever one of them is scanned.
The following example illustrates how to use the TruCode Scanner by loading it as a child Fragment
of another
Fragment
that's already in the foreground:
// 1
TruCodeHandler truCodeHandler = new TruCodeHandler() {
@Override
public void onTrusonaficationCreated() {
// The TruCode was successfully scanned. You may want to start monitoring for pending
// trusonafications at this point if you haven't done so yet.
}
@Override
public void onError(String payload) {
// There was an error while processing the TruCode
}
@NonNull
@Override
public Integer fragmentContainerId() {
// Update this method to return the id of the ViewGroup container into which the Trusona
// SDK will display the TruCode Scanner. This ID must be present in the layout of the fragment
// that's in the foreground and that's passed in to the loadTruCodeAsChildFragment() method.
// i.e.: R.id.tru_code_scanner_container.
return null;
}
};
// 2
IdentifierProvider identifierProvider = new IdentifierProvider() {
@Override
public String identifier() {
// Return your device's identifier
return null;
}
};
// 3
trusona.loadTruCodeAsChildFragment(myFragment, truCodeHandler, identifierProvider);
- Implement the
TruCodeHandler
interface, which will be notified when the Trucode has been scanned. - Implement the
IdentifierProvider
to return the device's identifier - 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 theFragment
passed as a parameter has been attached to its corresponding activity and is visible, for example, during it'sonViewCreated
method.
Alternatively, if you'd like to load the TruCode scanner in a layout that is not part of a Fragment
, the
getTruCodeFragment
method provides a Fragment
reference that can be loaded using an Activity's
SupportFragmentManager
.
In 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.
You'll want to arrange your custom views in such a way that they will be placed on top of the scanner's viewfinder.
The following xml layout file demonstrates how to do this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The id of this FrameLayout should match the one returned by your implementation of -->
<!-- TrucodeHandler's `fragmentContainerId()` method. -->
<FrameLayout
android:id="@+id/tru_code_scanner_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- TODO: Place any custom views you'd like to add below this line, so that they're laid -->
<!-- on top of the scanner -->
</FrameLayout>
Using this strategy, you can add any custom views you'd like on top of the scanner and you can set click
listeners or modify them as you would typically do: By getting a reference to them during myFragment
's
onCreateView
lifecycle method.
A Trusonafication occurs when a user attempts to access a protected resource, and the user is allowed to accept or deny the action. When a Trusonafication is received, the app needs to respond to confirm the user's identity. Depending on how the Trusonafication was created, this may involve a visual prompt requiring the user to accept and/or provide the credentials used to unlock the device.
Polling for in progress trusonafications should happen only when your application is in the foreground.
Typically you'll want to start the polling process in your Activity
's onResume
or onCreate
lifecycle
callback. The SDK will automatically stop the polling process for you during the onStop
lifecycle
callback, however, if you need to stop polling at a particular point in time, you may use the stop()
method of the PollerStopper
object returned by the startPolling
method.
A call to the startPolling
method requires an instance of AppCompatActivity
in order to start a new
SDK controlled Activity when a Trusonafication is received. The latter is invoked via the startActivityForResult
method, so the calling AppCompatActivity
must implement onActivityResult
in order to receive the
outcome of the processed Trusonafication
.
public class MyActivity extends AppCompatActivity {
private Trusona trusona = new Trusona();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1
trusona.startPolling(this);
}
// 2
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == TrusonaficationActivity.TRUSONAFICATION_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
// 3
Trusonafication trusonafication;
try {
trusonafication = TrusonaficationParser.getFromIntent(data);
}
catch (IllegalArgumentException e) {
trusonafication = null;
//Trusonafication not present in intent data
}
// 4
/* This Throwable will be returned if something goes wrong while processing a trusonafication. */
Throwable error = (Throwable) data.getSerializableExtra(TrusonaficationActivity.ERROR_KEY);
if (trusonafication != null && error == null) {
// 5
handleTrusonaficationResult(trusonafication);
}
else {
// 6
handleError(error);
}
}
}
private void handleError(Throwable error) {
// Some of the possible exceptions that can be received are:
if (error instanceof RequiredIdentityDocumentException) {
/* Used when a trusonafication required that the user
presents their Identity Document but they have not registered one to their account yet */
}
else if (error instanceof InvalidIdentityDocumentException) {
/* Used when the scanned Identity document is not in
AAMVA format or it was not accepted by the trusona servers. */
}
else if (error instanceof UnavailableDeviceSecurityException) {
/* Used when the trusonafication requires that the device has enabled a pin/pattern/password/biometric
but it hasn't. */
}
else {
//Unexpected type of exception
}
}
private void handleTrusonaficationResult(Trusonafication trusonafication) {
switch (trusonafication.getStatus()) {
case ACCEPTED:
// The trusonafication was successfully accepted by the user
break;
case REJECTED:
// The trusonafication was successfully rejected by the user
break;
case FAILED:
// The user attempted to accept or reject the trusonafication but an error occurred
break;
case EXPIRED:
// The user did not accept or reject the trusonafication during it's validity period,
// which by default is 2 minutes.
break;
case CANCELED:
// The trusonafication was cancelled
break;
case IN_PROGRESS:
// The trusonafication is still in progress. This means the user backed out of the trusonafication
// process, typically by sending the app to the background via the device's home button.
break;
default:
break;
}
}
}
- Call
trusona.startPolling(this)
during the Activity'sonCreate
method. - Override
onActivityResult
so you can receive the trusonafication result passed back by the SDK. - Use the
TrusonaficationParser
to acquire the processedTrusonafication
from the passed inIntent
. - Query the passed in
Intent
for any errors that may have been thrown during the trusonafication process. - If no errors were thrown, handle the trusonafication result by examining its
TrusonaficationStatus
. - If an error was thrown, handle accordingly.
If you'd like to acquire a single in-progress trusonafication, you can do so by calling the
fetchNexTrusonafication(TrusonaficationListener)
method of the Trusona
class.
Being an asynchronous method, this requires that you pass in an implementation of the TrusonaficationListener
interface, which will provide you with the callbacks to determine the right course of action depending on
whether a trusonafication was found or not.
In case a trusonafication is found, you may want to process it via one of the variants of the startTrusonaficationActivity
method.
// 1
TrusonaficationListener trusonaficationListener = new TrusonaficationListener() {
@Override
public void onTrusonafication(Trusonafication trusonafication) {
// This callback will execute if an in-progress trusonafication is found.
// You may want examine the trusonafication or request that the SDK
// processes it by calling:
// trusona.startTrusonaficationActivity(appCompatActivity, trusonafication);
}
@Override
public void onErrorFetchingTrusonafication(Throwable throwable) {
// This callback will execute if no trusonafication was found or
// if an error occured. You can examine the throwable parameter
// to determine which was the case.
}
};
// 2
trusona.fetchNexTrusonafication(trusonaficationListener);
- Implement the
TrusonaficationListener
interface. - Using a previously instantiated
Trusona
object, callfetchNexTrusonafication
, passing in your implementation of theTrusonaficationListener
interface.
The 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.
Note: 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 of a driver's license as part of the business logic in your application.
// 1
PDF417ScanHandler pdf417ScanHandler = new PDF417ScanHandler() {
@Override
public void onSuccess(@NonNull DriversLicenseScanResult result) {
// examine license properties as necessary
AAMVADriversLicense license = result.getDriversLicense();
// examine scanning event's metadata. This metadata is subject to change. Additionally,
// all properties may not be available for all scan results.
// Current available properties are:
// x - result of division of the x/y point of the top left corner
// y - result of division of the x/y point of the top right corner
// h - result of division of the x/y point of the bottom left corner
// w - result of division of the x/y point of the bottom right corner
// t - value returned by System.nanoTime()
//
Map<String, ?> metadata = result.getMetadata();
}
@NonNull
@Override
public Integer fragmentContainerId() {
// Return the ID of the ViewGroup in which the SDK will attempt to load the Driver
// License scanner. This ID must be present in the layout of the Fragment that's passed
// in as a parameter to the scanDriversLicense method, and the Fragment must have been
// brought into the foreground and be ready to host the Driver License scanner.
// i.e.: R.id.my_fragment_container.
return 0;
}
@Override
public void onDocumentError(Throwable throwable) {
// handle error case due to invalid document being scanned
}
};
// 2
trusona.scanDriversLicense(fragment, pdf417ScanHandler);
- Implement the
PDF417ScanHandler
interface. - Using a previously instantiated
Trusona
object, callscanDriversLicense
, passing a reference of the fragment into which the Driver License scanner will be inflated and the instance of the implementedPDF417ScanHandler
.
The 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.
// 1
PassportScanHandler passportScanHandler = new PassportScanHandler() {
@Override
public void passportScanned(PassportScanResult passportScanResult) {
// examine license properties as necessary
Passport passport = passportScanResult.getPassport();
// examine metadata properties as necessary
Map<String, Object> metadata = passportScanResult.getMetadata();
}
@Override
public void passportScanCanceled() {
// Handle what happens when the user taps the Cancel button.
}
@NonNull
@Override
public Integer fragmentContainerId() {
// Return the ID of the ViewGroup in which the SDK will attempt to load the Passport
// scanner. This ID must be present in the layout of the Activity that's passed
// in as a parameter to the getPassportScanner method, and the Activity must have been
// brought into the foreground and be ready to host the Passport scanner.
// i.e.: R.id.my_passport_scanner_container.
return 0;
}
};
// 2
trusona.getPassportScanner(activity, passportScanHandler);
- Implement the
PassportScanHandler
interface. - Using a previously instantiated
Trusona
object, callgetPassportScanner
, passing a reference of the activity into which the Passport scanner will be inflated and the instance of the implementedPassportScanHandler
.
Users 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.
Before doing the upgrade, it is important to make sure the device identifier of the running app has been bound to an account.
The following code snippet illustrates the required step:
// 1
PDF417UpgradeHandler pdf417UpgradeHandler = new PDF417UpgradeHandler() {
@Override
public void onSuccess(@NonNull IdentityDocument<DriversLicenseScanResult> identityDocument) {
// This method will be called when the user was succesfully upgraded, which means
// now you can authenticate them at Executive level.
// You may examine the returned IdentityDocument instance as necessary and get a
// DriversLicenseScanResult instance to examine via the following method:
DriversLicenseScanResult driversLicenseScanResult = identityDocument.getDocument();
}
@NonNull
@Override
public Integer fragmentContainerId() {
// Return the ID of the ViewGroup in which the SDK will attempt to load the Driver
// License scanner. This ID must be present in the layout of the Fragment that's passed
// in as a parameter to the upgradeToExecutive method, and the Fragment must have been
// brought into the foreground and ready to host the Driver License scanner.
// i.e.: R.id.my_fragment_container.
return 0;
}
@Override
public void onDocumentError(Throwable throwable) {
// handle error case due to invalid document being scanned
}
};
// 2
trusona.upgradeToExecutive(fragment, pdf417RegisterHandler);
- Implement the
PDF417UpgradeHandler
interface. - Using a previously instantiated
Trusona
object, callupgradeToExecutive
, passing a reference of the fragment into which the Driver License scanner will be inflated and the instance of the implementedPDF417RegisterHandler
.
During 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:
- A visual prompt that gives the user the choice of accepting or rejecting the Trusonafication
- An operating system authentication (e.g. Fingerprint, Pattern, PIN)
- Scanning of driver's license
The prompt and scanning screens can be customized by passing an instance of the TrusonaficationUICustomizations
interface to the variants of the
startPolling
or startTrusonaficationActivity
methods that receive one as a parameter. If you don't pass in a TrusonaficationUICustomizations
implementation, then a default dialog and scanner UI will be used.
The TrusonaficationUICustomizations
interface has five methods:
boolean usesCustomDialog()
: Set the return value to true if you'd like to provide a custom prompt/dialog.Dialog trusonaficationDialog(Context context, Trusonafication trusonafication)
: If you set the return value ofusesCustomDialog()
to true, then you will need to create and return your custom prompt in this method. Otherwise, you can return null.boolean usesCustomDLScanner()
: Set the return value to true if you'd like to provide a custom scanner UI.Fragment getCustomDLScanner(Trusonafication trusonafication)
: If you set the return value ofusesCustomDLScanner()
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.Integer getDLScannerContainerId()
: If you set the return value ofusesCustomDLScanner()
to true, then this method must return theid
of the container in which you want to host the scanner. Thisid
has to be defined in theXML layout
used by theFragment
returned by thegetCustomDLScanner(Trusonafication trusonafication)
method. You may return null if you're not using a custom Driver License Scanner.
It's important to note that Activities
nor Fragments
should implement the TrusonaficationUICustomizations
interface, as the SDK will
maintain a reference to it while it's own Activity
handles the Trusonafication
flow.
// 1
TrusonaficationUICustomizations trusonaficationUICustomizations = new TrusonaficationUICustomizations() {
@Override
public boolean usesCustomDialog() {
// Update the return value to indicate whether you'd like to use a custom prompt dialog or not
return true;
}
@Override
public Dialog trusonaficationDialog(Context context, Trusonafication trusonafication) {
// In order to customize the UI used to prompt users to accept or reject
// trusonafications, you can return a Dialog that inflates the xml layout
// you'd like to use.
//
// You may customize the views in your Dialog by acquiring a reference to them via the
// dialog.findViewById() method and then applying any changes you see fit, like adding
// onCLickListeners, applying spans to TextViews, etc.
//
// When using a custom Dialog, the layout it inflates must contain the following views so
// that the sdk can properly process the accept and reject actions of the user:
//
// * A View with the id `trusonafication_accept_button`
// * A view with the id `trusonafication_reject_button`
//
// The following code returns a full screen dialog that uses the my_trusonafication_layout
// xml file:
Dialog dialog = new Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.my_trusonafication_layout);
// Note: Do not call the show method of the dialog instance. The SDK will do that
// at the appropriate moment. Also, if usesCustomDLScanner() returns false, this
// method may return null.
return dialog;
}
@Override
public boolean usesCustomDLScanner() {
// Update the return value to indicate whether you'd like to use a custom Driver License Scanner or not
return true;
}
@Override
Fragment getCustomDLScanner(Trusonafication trusonafication) {
// Update this method to return an instance of the Fragment onto which you want to
// load the Driver License Scanner or null if your application does not require
// Driver License scanning. The Fragment must be loaded by the FragmentManager
// before being returned.
//
// You may inspect the IN_PROGRESS Trusonafication which is passed as a parameter and
// perform any UI updates necessary.
//
// Note: If usesCustomDLScanner() returns false, this method may return null.
//
// Sample implementation:
return MyFragment.newInstance();
}
@IdRes
@Override
public Integer getDLScannerContainerId() {
// Update this method to return the id of the ViewGroup container into which the Trusona
// SDK will display a Driver License Scanner if a Trusonafication requires it. This ID must
// be present in the layout of the Fragment returned by the `getCustomDLScanner` method implementation in
// this class. Alternatively, this can be null if your application does not require identity
// document scanning.
//
// Note: If usesCustomDLScanner() returns false, this method may return null.
//
// Sample implementation:
return R.id.my_fragment_container;
}
};
// 2
trusona.startPolling(appCompatActivity, trusonaficationUICustomizations);
- Implement the
TrusonaficationUICustomizations
interface. The layout used by the Dialog created in thetrusonaficationDialog(Context context, Trusonafication trusonafication)
method can be styled in any way but it must contain the following views to be properly rendered and to allow the sdk to process accepting and rejecting the trusonafication:
- A View with the id
trusonafication_accept_button
- A view with the id
trusonafication_reject_button
- Using a previously instantiated
Trusona
object, callstartPolling
(orstartTrusonaficationActivity
), passing an instance of the implementedTrusonaficationUICustomizations
. Usually, you would do this in yourActivity
'sonResume
oronCreate
method.
When creating a Trusonafication from one of the server SDKs, it is possible to include a set of custom fields on the Trusonafication.
These custom fields are made available in your implementation of TrusonaficationUICustomizations
when the trusonaDialog(Context context, Trusonafication trusonafication)
and getCustomDLScanner(Trusonafication trusonafication)
callback methods are called and a Trusonafication is passed in as a parameter to them.
The custom data will be available in the customFields
property of the Trusonafication. By inspecting the custom data in these fields, the
dialog behavior can be customized or the data can be shown in the dialog UI.
Your mobile application needs to be configured to handle deep links so that it can receive the data passed by the Trusona web SDKs to the Trusona mobile SDKs. Depending on your minimum supported Android version, this may mean you'll need to configure App links and intent filters for incoming links as well. For more information on how to do this, take a look at the official Android Developers documentation here and here.
When deeplinking, Trusona will redirect users to your application using this url:
<scheme>://<handle>.applaunchexpress.com/trucode?payload=XXXXXXXXXXXXXXXX
The scheme
will depend on whether you are using App links or a custom scheme. The former will use https
and the later a
scheme of your choice. The handle
will be provided by Trusona and is unique to your application.
Once one of your Activities has been set up to handle deep links, it will need to implement the following steps:
//1
TruCodeHandler deepLinkTruCodeHandler = new TruCodeHandler() {
@Override
public void onTruCode(boolean success) {
if(success) {
// the deeplink trusonafication was successfully accepted and validated.
}
else {
// There was an error while processing the deeplink trusonafication.
}
}
@Nullable
@Override
public Integer fragmentContainerId() {
// Update this method to return the id of the ViewGroup container in which the accept / reject
// prompt will be loaded. This ID must be present in the layout of the fragment passed to the `handleTruCodeDeepLink`
// method.
return null;
}
@Nullable
@Override
public Integer acceptRejectLayoutId() {
// Update this method to return the id of the layout that will be used to prompt users
// to accept or reject trusonafications. Alternatively, return null to use the default OS
// alert dialog.
return null;
}
};
// 2
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Your code goes here
// 2.1 Load the fragment that will host the accept / reject prompt.
// 2.2
trusona.handleTruCodeDeepLink(fragment, deepLinkTruCodeHandler, getIntent().getData());
}
@Override
protected void onStop() {
super.onStop();
// Your code goes here
// 3
trusona.stopPendingTrusonaficationsMonitor();
}
- Provide an implementation of the
TruCodeHandler
interface. - Update your activity's
onCreate
method to:
- Load the fragment that will host the accept / reject prompt.
- Use an existing instance of the Trusona class to call
handleTruCodeDeepLink
passing in a reference to the fragment loaded in the previous step, theTruCodeHandler
implementation from step 1, and the deep link payload acquired by callinggetIntent().getData()
.
- Update your activity's
onStop
method to callstopPendingTrusonaficationsMonitor
.
Contact us at engineering@trusona.com