SDK for Android 

Introduction 

The IDEMIA Verify SDK for Android provides customers with the resources to customize the SDK to their preferred user-experience and integrate it within an existing mobile application. The IDEMIA Mobile ID Verify App works in conjunction with the IDEMIA Mobile ID App allowing verifiers to authenticate the user's physical ID or digital credential (i.e. drivers license or identity card).

You can use the SDK to:

  • Create and design your preferred user-experience and UI while leveraging the IDEMIA Verify functionalities

    You can build a custom mobile application that implements your user-experience design and leverages all of the SDK functionalities allowing you to apply your branding and preferred user flow. You maintain complete control over the display and functionality of the application.

  • Embed IDEMIA Verify into an existing application

    You can automatically integrate an existing mobile application with IDEMIA by adding the SDK frameworks, which removes the need to use and maintain an additional application to leverage the Mobile ID's functionalities.


Get Started 

Skills Required 

The integration tasks should be done by developers with knowledge of:

  • Android Studio
  • Java/Kotlin for Android
  • Android SDK
  • Android operating system

Resources Required 

Integrations may be performed on PC Windows, Linux, or Macintosh.

  • Android Studio Koala | 2024.1.1 or above
  • Android SDK tools: preferred latest version (release 34 or above)
  • JDK: preferred latest version (8 or above)
  • Android device (emulator is not supported)
  • Minimum SDK version is 30 (Android 11)

Other Requirements 

Tech Stack
Description
Development environmentAndroid Studio Flamingo 2022.2.1+, Windows, Mac or Linux, JDK 8.. JDK17
Programming languageKotlin, Java
Kotlin Version1.8.20
Minimum supported OS VersionAndroid 11.0 (API 30)
Target SDK versionAndroid 14.0 (API 34)

Components 

The SDK is made up of the following components:

  • IDVerify acts as the entry point for initializing device engagement. It sends the request to the Mobile ID credential holder, receives the response, and sends the parsed model back to the calling app. It exposes the following APIs to the caller/client:

SDK Core APIs

  • version
Kotlin
1/**
2* returns build version if IDVerify sdk in <versionName>-<VersionCode> format.e.g. 4.2.0-134
3* Integrators can use this information to know and validate IDVerify version they are to integrate in their app.
4* /
5
6//Usage
7Log.d(TAG, "SDK Version=${IDVerify.version}")
  • initializeSDK
Kotlin
1/**
2 * Call this static function to activate the license very first time before initialising IDVerify.
3 * @param lkmsConfig : Model class containing with license configurations details e.g. APIKey, ActivationId etc.
4 * @param context: application context
5 * @param callback : return success or error
6 * returns error or success callback
7 * Note: It is mandatory to call initializeSDK function at least once when reader app loads -- with valid license configurations.
8 * Using any other IDVerify APIs without calling this function might result in error.
9 */
10fun initializeSDK(lkmsConfig: LkmsConfig?, context: Context?, callback: SuccessCallback<Boolean>)
  • getClient
Kotlin
1/**
2 * Create and return IDVerify client object.
3 *
4 * @param configs – required configurations to initialize IDVerify instance
5 * @param actContext; activity context from app.. you can provide an application or
6 * Activity context however some features e.g. NFC, WifiAware it is strictly required
7 * Activity context; hence it is recommended to use Activity context. It is also recommended
8 * that your app maintain a singleton object of SDK to avoid any concurrency issues.
9 *
10 * @return `IDVerify` interface to access the ISO reader APIs
11 */
12
13fun getClient(configs: VSDKConfigs, actContext:Context): IDVerify
  • loadCertificates
Kotlin
1/**
2 * Load certificates from a given location from device storage path
3 * @param path from device storage if accessible directly; defaults to null if not supplied
4 * @param vical file path from device storage if accessible directly.
5 * defaults to null if not supplied and fallback to load vical from assets/vical folder if available
6 * @param callback async callback to return success or error
7 */
8
9fun loadCertificates(path: String?=null,callback: SuccessCallback<Int>?)
  • initDeviceEngagement
Kotlin
1/**
2 * perform device engagement using QR code / NFC
3 * @param apiConfigs apiConfigs to configure QR code/NFC flow etc.
4 * Uses:
5val apiConfigs = ApiConfigs.Builder()
6.withData(scannedData) // for qr code device engagement
7//OR .withConfigs().useNfcHandover().buildConfigs() //for nfc device engagement
8.build()
9
10 * @param deviceEngagementCallback callback to return the DeviceEngagement model
11 * and/or other events during engagement.
12 * Usage:
13<p>
14sdkClintV2.initDeviceEngagement(apiConfigs,object:DeviceEngagementCallback(){
15//override the interface methods here
16})
17</p>
18 */
19fun initDeviceEngagement(apiConfigs: ApiConfigs?, callback: DeviceEngagementCallback<in ResponseItem?>)
  • prepareConnection
Kotlin
1/**
2 * Initialize and setup connection components as per`ConnectionConfigs` configurations supplied.
3 * This API is available in `IDVerify` only and must be called explicitly if SDK client
4 * is created using `IDVerify.getClient`.
5 */
6
7fun prepareConnection(apiConfigs: ConnectionConfigs, callback: PrepareConnectionCallback?)
  • sendRequest
Kotlin
1/**
2 * send request to Mobile ID based on the use case selected by user in Verify application
3 * @param apiConfigs: configurations and optional Mobile ID request params
4 * @param callback: callback to send progress and response data back to app
5 *
6 * 1. create Mobile ID request based on supplied Use Case or parameters/configs
7 * 2. onCreate communication channel (BLE/NFC/wifiAware ...) as per engagement data
8 * 3. send request to Mobile ID on communication channel
9 */
10fun sendRequest(apiConfigs: ApiConfigs? = ApiConfigs.Builder().build(),
11 callback: ICallback<in ResponseItem?, in ProgressItem>)
  • cancelRequest
Kotlin
1/**
2 * cancel any transaction/running session with Mobile ID. overload to default cancellation
3 * return true if transaction is cancelled successfully
4 */
5fun cancelRequest(): Boolean
  • terminateConnection
Kotlin
1/**
2 * Terminate the current connection to let user call prepareConnection again.
3 */
4fun terminateConnection(): Boolean
  • terminateSession
Kotlin
1/**
2 * Terminate/Close the connection, wipe out session data and ready to process next transaction from
3 * user.
4 */
5fun terminateSession(): Boolean
  • isRequestOngoing
Kotlin
1/**
2 * Check whether a transaction is already setup and in-progress state. Integrator can use this
3 * api to check a running transaction and cancel (if needed using `cancelRequest`) before
4 * starting a fresh transaction.
5 * Normally this api may not be used because once the transaction is complete verify SDK will return
6 * to initial state, however in case of some negative test cases it may be useful to check before
7 * starting a new transaction.
8 */
9fun isRequestOngoing(): Boolean

User Permissions 

When designing your app, you need to consider that your Android app must handle end-user permissions to protect the resources on the target mobile device. You have to verify that the end-user grant the following permissions to the app:

  1. Camera permission (for QR code scanning using Camera)
  2. Location permission (when BLE client mode and WiFiAware use cases)
  3. Nearby devices permission required for WiFiAware use case (android 13 and above)

The end-user must grant access when using an Android version higher than 2.3 (Android 6.0 Marshmallow). The SDK will throw an exception or error, if the required permissions are not granted.


Sample Project 

Download the IDEMIA Verify Sample App – Android using below URL: https://mi-artifactory.otlabs.fr/artifactory/verify-sdkpro-release/com/idemia/android/idverify/4.2.0/Sample/


Create Your Own App 

Follow the steps mentioned below to Integrate the VerifySDK in your App:

Step 1: Add the Verify Library dependencies in your Android project 

To create your own app, you must add the VerifySDK libraries to your project. There are two ways of doing this:

** Import VerifySDK from mi-artifactory**

  1. Add the following configs in gradle.properties as shown in the snippet:
Groovy
1artifactory_remoteUrl=https://mi-artifactory.otlabs.fr/artifactory/verify-sdkpro-release
2artifactory_username=<username>
3artifactory_password=<password>
  1. Add the following dependency in your project/build.gradle as shown in the snippet:
Groovy
1buildscript {
2
3 repositories {
4 google()
5 jcenter()
6 maven {
7 url "https://plugins.gradle.org/m2/"
8 }
9 //required below maven block to sync verify SDK artifact from mi-artifactory
10 maven {
11 url "${artifactory_remoteUrl}"
12 credentials {
13 username = "${artifactory_username}"
14 password = "${artifactory_password}"
15 }
16 }
17
18 }
19 ...
20 }
21 ...
22
23 allprojects {
24 repositories {
25 ...
26 maven { url 'https://github.com/c-rack/cbor-java' }
27 maven {
28 url "${artifactory_remoteUrl}"
29 credentials {
30 username = "${artifactory_username}"
31 password = "${artifactory_password}"
32 }
33 }
34
35 }
36 project.ext{
37 sdkVersionName='4.2.0'
38 sdkVersionCode=134 //use latest release version number for v4.2.0 from mi-artifactory
39
40 }
41
42 }
  1. Add following dependency in app/build.gradle as shown in the snippet:
Groovy
1dependencies {
2 implementation("com.idemia.android:idverify:${project.ext.sdkVersionName}-${project.ext.sdkVersionCode}@aar") {
3 transitive = true
4 }
5 ...
6}

Additional Steps to Compile and Build your Android project

  1. Add the required permissions to the project:
XML
1<!-- required camera for QR code scanning-->
2 <uses-permission android:name="android.permission.CAMERA"/>
3 <uses-feature android:name="android.hardware.camera.any" />
4 <!-- Request legacy Bluetooth permissions on older devices. -->
5 <!-- required for BLE data transfer-->
6 <uses-permission android:name="android.permission.BLUETOOTH"
7 android:maxSdkVersion="30"/>
8 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
9 android:maxSdkVersion="30"/>
10 <!--BLE permissions for Android 12-->
11 <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
12
13 <!-- Needed only if your app makes the device discoverable to Bluetooth
14 devices. -->
15 <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
16
17 <!-- Needed only if your app communicates with already-paired Bluetooth
18 devices. -->
19 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
20
21 <!-- required for wifiaware and BLE scanning -->
22 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
23 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
24 <!--Required for online use cases -->
25 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
26 <uses-permission android:name="android.permission.INTERNET" />
27 <!-- required for wifiaware data transfer-->
28 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
29 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
30 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
31 <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation"/>
32 <!-- required for nfc data transfer-->
33 <uses-permission android:name="android.permission.NFC"/>
  1. In order to allow your app to install in devices which do not support a certain feature, below lines can be added just below the permissions:
XML
1<!-- Do not install in devices which do not have Camera -->
2 <uses-feature android:name="android.hardware.camera" android:required="true"/>
3 <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
4 <!-- allow app to install in devices which do not have NFC support so that
5 they can still use other features e.g QR code and WifiAware use-cases -->
6 <uses-feature android:name="android.hardware.nfc" android:required="false"/>
7 <!-- allow app to install in devices which do not have wifiAware support so that
8 they can still use other features e.g QR code and NFC use-cases -->
9 <uses-feature android:name="android.hardware.wifi.aware" android:required="false"/>

Note: It is not recommended to have all three configs with required="false". Normally if all three use cases (QR Code, NFC handover/transfer, WifiAware Transfer) are supported in your app then you may want to let users install your app regardless of their device supports or not NFC and/or WifiAware; for that you can add required="false" for WifiAware and NFC and required="true" for Camera.

  1. Gradle Sync and build!

Step 2: Integrate QR Code + BLE/NFC/WiFi Use case 

  1. Initialize the ID Verify SDK by providing a valid license information in initializeSDK API. Best way to do it is when your application's Home Activity is loaded inside the onCreate function:
Kotlin
1override fun onCreate(savedInstanceState: Bundle?) {
2 super.onCreate(savedInstanceState)
3 initIdVerify(getLicenseConfigs())
4
5 //.. other code here
6 // setupQRCodeScanner(scanMode)
7 }
8
9 private fun initIdVerify(lkmsConfig: LkmsConfig) {
10 IDVerify.initialiseSDK(lkmsConfig,this,object: SuccessCallback<Boolean> {
11 override fun onSuccess(status: Boolean?) {
12 //show/log any message or keep silent
13 }
14 override fun onError(error: IError?) {
15 //display error as returned by ID Verify SDK. and prompt the user to exit the app since ID Verify SDK can not function until this error is fixed.
16 }
17 })
18 }
19
20 /**
21 * License configs can be managed as BuildConfig fields and loaded at runtime.
22 */
23 protected open fun getLkmsConfigs(): LkmsConfig {
24 return LkmsConfig(
25 BuildConfig.lkmsURL,
26 BuildConfig.lkmsProfileId,
27 BuildConfig.lkmsApiKey,false)
28 }
  1. Once the ID Verify SDK is initialized with a valid license, you may create the IDVerify object to access all the Verifier APIs. Below code snippet shows how to create IDVerify interface mIdVerify:
Kotlin
1val config = VSDKConfigs.Builder().build()
2 mIdVerify = IDVerify.getClient(config,actContext)

Important:

  • While building VSDKConfigs you may use enableDebug function to get the live logs via DebugCallback and save them in a file, as shown in the snippet:
Kotlin
1val config = VSDKConfigs.Builder(this)
2 .enableDebug(LogLevel.DEBUG,debugCallback = object:DebugCallback{
3 override fun didReceiveLogs(logs: DLog) {
4 //save or print logs here
5 //
6 }
7 })
8 ...
9 .build()

Note: It is recommended to save the logs into a file and then print or share the file to see the full logs. Because logcat strips logs if they are too big to fit in console.. for example, response bytes with end-user image becomes too big to print in logcat.

  • Enabling debug verbose logs in the production app may adversely affect the transaction speed and overall performance of the Verify SDK for Android.
  • It is recommended that integrator should use the LogLevel properties carefully to configure limited logs in production flavour.
  • Default LogLevel will be NONE if enableDebug is not configured with at least one LogLevel
  • If you want full debug logs except PIIs then use DEBUG_NO_PII
  • DEBUG and VERBOSE may include PIIs hence should be avoided in production release
  • Supported LogLevel are:
Language not specified
1TRANSACTION_TIME : Only transaction time event logs shall be printed on console and returned to`debugCallback.didReceiveLogs()`
2 These logs shall be persisted in runtime memory during the transaction and shall be dumped
3 to console in a time sorted order (FIFO) once the transaction concludes.
4
5 TROUBLESHOOTING : Only minimal troubleshooting logs (e.g. exceptions and errors) shall be printed on console and
6 returned to `debugCallback.didReceiveLogs()`.
7 These logs would be helpful to troubleshoot the failures cases during transactions.
8
9 DEBUG : All debug logs include PIIs are returned or printed in console
10
11 DEBUG_NO_PII : All except PII logs shall be returned to `debugCallback.didReceiveLogs()` LogLevel.DEBUG_NO_PII has highest priority
12 if multiple logLevel values are configured via `enableDebug` vararg param. (excluding LogLevel.NONE- in case of NONE is found,
13 all other configs shall be ignored and all logs shall be disabled)
14
15 VERBOSE : Allow all logs (transaction_time, troubleshooting, and Debug) including PIIs
16
17 NONE : No logs shall be printed. LogLevel.NONE has highest priority if multiple
18 logLevel values are configured via `enableDebug` vararg param

2.1. Call loadCertificates() api to load IACA certificates from given path. This step is necessary for a successful transaction since Verify SDK will validate the mDL response against the certificates from supplied path.

Kotlin
1mIdVerify?.loadCertificates(path=<directory_path/vical>,object : SuccessCallback<Int> {
2 override fun onSuccess(response: Int?) {
3 Log.d("HomeFragment","*Certificate Loading, loaded cert count:$response")
4
5 }
6 override fun onError(error: IError?) {
7 Log.d("HomeFragment","*Certificate Loading error: ${error?.errorCode}")
8 }
9 })

How to create directory structure for hosting vical files for your Reader app?

  • Copy download vical files at some app private location which should be accecisble at runtime
  • Create new directory vical/ inside assets and copy iaca files for each environment as per below structure.
  • assets/vical
    • Dev
      • iaca.vical
      • iaca.vical.pem
    • UAT
      • iaca.vical
      • iaca.vical.pem
    • PROD
      • iaca.vical
      • iaca.vical.pem

Note:

  • The vical file and corresponding IACA file to validate vical coseSign1 should be named exactly as in above sample
  • For example, if vical file name is "myiaca.vical" then IACA should be named "myiaca.vical.pem"

How To configure vical from app/assets directory?

  • Create 'assets/vical' folder inside app/main or app/flavorName/
  • Copy iaca and corresponding IACA cert per environment similar to structure defined above.
  • Set value for path to null while calling loadCertificates api and verifySDK shall fallback to use assets/vical path
Kotlin
1.loadCertificates(path=null,callback=object :SuccessCallback<Int>{
2 override fun onSuccess(response: Int?) {
3 //Log.d("HomeFragment","*Certificate Loading, loaded cert count:$response")
4 }
5
6 override fun onError(error: IError?) {
7 //Log.d("HomeFragment","*Certificate Loading error: ${error?.errorCode}")
8 }
9
10 })

Note:

  • loadCertificates() api should be called only once on application launch when SDK object is created first; no need to be called for each transaction.
  1. Call the desired SDK API by supplying the necessary apiConfigs/request parameters and using callback to receive the results.
Kotlin
1* `mIdVerify.initDeviceEngagement(apiConfigs,callback)`
2* `mIdVerify.prepareConnection(connectionConfigs,callback)`
3* `mIdVerify.sendRequest(apiConfigs,callback)`
4* `mIdVerify.terminateConnection()`
5* `mIdVerify.terminateSession()`
6*
  1. To scan the QR code follow the below steps to communicate with the Mobile ID App and display the results on the Verify App screen:
  • Scan the QR code using Zxing or any other library and then call initDeviceEngagement API as shown in the snippet:
Kotlin
1fun onQRCodeScanned(scannedData: String?) {
2 doHandleScannedData(scannedData)
3 }
  • Create the response callback for parsing engagement QR code data as shown in the snippet:
Kotlin
1open fun doHandleScannedData(scannedData: String?) {
2 if (!scannedData.isNullOrEmpty()) {
3 val nfcConfigsBuilder=NfcConfigs.Builder()
4 val apiConfigs = ApiConfigs.Builder()
5 .withData(scannedData)
6// //OR useNfcHandover() as below commented section//for nfc device engagement
7// .withConfigs().apply {
8// useNfcHandover()
9// /* use additional configs for nfcHandover if needed
10// * verify sdk will use default and best ppossible configs if no configs are
11// * set using `setNfcConfigs`
12// */
13//
14// nfcConfigsBuilder.enableReaderEngagement() //use this cofig to enable readerEngagement bytes ON for Nfc negotiated handover
15// nfcConfigsBuilder.enableWiFiACRecord(true) //use this to indicate support for WiFiAware
16// nfcConfigsBuilder.leRole(LeRole.MDOC_CENTRAL_ONLY) // use this to indicate preferred LE Role
17// //... // additional configs to fine tune based on underlying hardware/device/OS if needed
18// setNfcConfigs(nfcConfigsBuilder.build())
19// }
20// .buildConfigs()
21 .build()
22 mIdVerify?.initDeviceEngagement(apiConfigs, mDEParserCallback)
23 } else {
24 // QR scan failed! try again
25 }
26 }
27 /** Response callback for parse engagement QR code data */
28 private val mDEParserCallback = object : ResponseCallback<DeviceEngagementModel?> {
29 override fun onSuccess(deviceEngegmentModel: DeviceEngagementModel?) {
30 // deviceEngegmentModel received. perform next step
31 doPrepareConnection(deviceEngagementModel)
32 // OR for legacy client
33 // doStartDataTransfer(deviceEngagementModel)
34 }
35 override fun onError(error: IError?) {
36 handleError(error)
37 }
38 }
  1. Call prepareConnection api before calling sendRequest else skip to step 5.1
Kotlin
1private fun doPrepareConnection(deModel: DeviceEngagementModel?) {
2 val connectionConfigs = ConnectionConfigs.Builder()
3 .withConfigs().apply {
4 setResponseTimeout(10000) //sdk will disconnect and return with error code 303 if transaction doesn't complete in this time
5 setConnectTimeout(10000) //sdk will return with error code 206 is connection not established withing this time
6 //enableL2Cap() //to enable BLE l2cap if available and supported
7
8 }.buildConf()
9 .build()
10 mIdVerify?.prepareConnection(connectionConfigs,
11 object : PrepareConnectionCallback {
12 override fun onSuccess(response: ConnectionInfo?) {
13 when (response?.connectionState) {
14 ConnectionState.CONNECTED -> {
15 doStartDataTransfer(deModel)
16 }
17 else -> {
18 Log.d("MainActivity","prepareConnection: connectionState=${response?.connectionState}")
19 }
20 }
21 }
22
23 override fun onError(error: IError?) {
24 handleError(error)
25 }
26 })
27 }

5.1. Send the request to the Mobile ID App to get the credential details. The sendRequest() method will return the response from the user's Mobile ID App. If you've received it successfully, then you can display all the attributes of the Mobile ID App response in your own result activity, as shown in the snippet:

Kotlin
1private fun doStartDataTransfer(deModel: DeviceEngagementModel?) {
2
3 val namespaceParamMap = getRequestedParamsMap() // make map of namespace to List<MIDRequestParam>
4
5 val apiConfigs = ApiConfigs.MIDRequestBuilder()
6 .version("1.0")
7 .withConfigs().apply {
8 //verify sdk will disconnect and return with error code 303 if transaction doesn't complete in this time
9 setResponseTimeout(20000)
10 //verify sdk will return with error code 206 is connection not established withing this time
11 setConnectTimeout(10000)
12 clearBLECache() // enable BLE cache to clear for every transaction to avoid connection issues
13 //for wifiaware data transfer; since v2.4.0
14 setNANConfigs(NANConfigs.Builder().apply {
15 setSubscribeType(DEFAULT_NAN_SUBSCRIBE_TYPE)
16 setTtlSec(15)
17 }.build())
18 }.buildConf()
19 //add docType
20 .addDocType(DOCTYPE_18013_5).apply {
21 // pass all request params as Map<namespace->List<MIDRequestParam>
22 addParams(namespaceParamMap)
23 //OR use namespace -> param overload to add all params one by one
24 addParam("org.aamva.us", MIDRequestParam(REAL_ID))
25 addParam("org.aamva.us", MIDRequestParam("<AttributeName>"))
26 //OR use another overload to . duplicate params shall be removed if found
27 addParams(DEFAULT_NAMESPACE_18013_5_1, namespaceParamMap.get(DEFAULT_NAMESPACE_18013_5_1))
28 addParams(NAMESPACE_ORG_ISO_AAMVA, namespaceParamList.get(NAMESPACE_ORG_ISO_AAMVA))
29 //OR this way
30 addParams(
31 "my.custom.namespace2", listOf(
32 MIDRequestParam("custom_param_nm21"),
33 MIDRequestParam("custom_param_nm22"),
34 MIDRequestParam("custom_param_nm23"),
35 MIDRequestParam("custom_param_nm21") //duplicate
36 )
37 )
38 //OR use 3rd overload to pass params one by one
39 .addParam("my.custom.namespace", MIDRequestParam("custom_param1"))
40 // add requestInfo as map
41 .addRequestInfo(
42 infoMap = hashMapOf(
43 "reqKey1" to "reqVal1",
44 "reqKey2" to "reqVal2",
45 "reqKey3" to false,
46 "reqKey4" to 3334
47 )
48 )
49 //or use other overload to add one by one
50 .addRequestInfo("reqinfo1", "value1")
51 .addRequestInfo("reqinfo2", "value2")
52 .addRequestInfo("reqinfoLong", 180L)
53 .addRequestInfo("reqinfoBool", true)
54 .addRequestInfo("reqinfoBytArr", "sdkghdkgs".toByteArray())
55 .addRequestInfo("reqinfoDouble", 3.7)
56 .addRequestInfo("reqinfoFloat", 3.7F)
57 // add as dataItem
58 .addRequestInfo(
59 "reqinfoDataItem",
60 CborBuilder().addArray().add(1).add("item2").add("item3").end().build()
61 .first()
62 )
63
64 }.buildDoc()
65 //add another docType
66 .addDocType("my.cusom.docType.custom").apply {
67 addParams(
68 "my.custom.namespace2", listOf(
69 MIDRequestParam("custom_param_nm21", true),
70 MIDRequestParam("custom_param_nm22"),
71 MIDRequestParam("custom_param_nm23"),
72 MIDRequestParam("custom_param_nm21", true) //duplicate
73 )
74 )
75 // add requestInfo as map
76 .addRequestInfo(
77 infoMap = hashMapOf(
78 "reqKey1" to "reqVal1",
79 "reqKey2" to "reqVal2",
80 "reqKey3" to false,
81 "reqKey4" to 3334
82 )
83 )
84 }.buildDoc()
85 //(optional) setReaderAuthentication callback if needed
86 .setReaderAuthCallback(readerAuthSigner,ReaderAuthAlgorithm.ALGO_SHA256WITHECDSA)
87 //(optional) Use setMultiRequestCallback to enable multiple requests-response exchanges within same session.
88 .setMultiRequestCallback(multiResCallback)
89 .build()
90
91 if (deModel?.isMDLAsPeripheral()) {
92 askLocationPermission() /* android.permission.ACCESS_COARSE_LOCATION to be added in AndroidManifest.
93 you may invoke all permission dialogs beforehand to avoid this check here*/
94 //mIdVerify?.sendRequest(apiConfigs, callback = mRequestCallback) //get permission and then call sendRequest
95 } else {
96 mIdVerify?.sendRequest(apiConfigs, callback = mRequestCallback)
97 }
98
99 }
100
101 fun getRequestedParamsMap(): java.util.HashMap<String, List<MIDRequestParam>> {
102 val paramMap= hashMapOf<String, List<MIDRequestParam>>()
103 paramMap.put(NAMESPACE_18013_5,listOf(
104 MIDRequestParam(FAMILY_NAME),
105 MIDRequestParam(GIVEN_NAME),
106 MIDRequestParam(BIRTHDATE),
107 MIDRequestParam(ISSUE_DATE),
108 MIDRequestParam(EXPIRY_DATE),
109 MIDRequestParam(ISSUING_COUNTRY),
110 MIDRequestParam(ISSUING_AUTHORITY),
111 MIDRequestParam(DOCUMENT_NUMBER),
112 MIDRequestParam(PORTRAIT),
113 MIDRequestParam(MGMT_LAST_UPDATE)))
114
115 paramMap.put(NAMESPACE_ORG_ISO_AAMVA,listOf(MIDRequestParam(DHS_COMPLIANCE),
116 MIDRequestParam(DOMESTIC_DRIVING_PRIVILEGES)))
117
118 return paramMap
119 }

**Sample code for Reader Authentication callback implementation **

Reader Authentication is an optional setReaderAuthCallback which can be used by the integrator to implement Reader Auth for their Verifier app. Below sample code spec illustrates how Reader Authentication callback can be implemented:

a. Add/Enable the callback in the RequestBuilder

Kotlin
1val apiConfigs = ApiConfigs.MIDRequestBuilder()
2 .version("1.0")
3 .addDocType("my.cusom.docType.custom").apply {
4 addParams()
5 }.buildDoc()
6
7 .setReaderAuthCallback(readerAuthSignerCallback,readerAuthAlgorithm)
8 .build()

b. Implement the readerAuthSignerCallback at app side. ReaderAuthSignerCallback provides the interface to perform signing of readerAuthentication structure. Verify SDK will call doSignRequest with the readerAuthentication structure to sign by the integrator with the reader private key. They will sign the bytes using certificate private key and return ReaderAuthSign data model with generated signature, algorithm used to sign and a x509 certificate with the corresponding public key of the private key that the readerAuthenticationBytes structure is signed. [Refer 9.1.4 mdoc reader authentication ISO/IEC FDIS 18013-5:2021(E) page 54]

Kotlin
1val readerAuthAlgorithm = ReaderAuthAlgorithm.ALGO_SHA256WITHECDSA
2 val readerAuthSigner=object : ReaderAuthSignerCallback {
3 override fun doSignItemRequest(readerAuthenticationStructure: ByteArray?,docType:String): ReaderAuthSign? {
4 // Verify SDK provides some utility functions in VIDUtils which can be used or write your own logic to generate the signature
5 val signatureBytes = VIDUtils.generateReaderAuthSignature(readerAuthAlgorithm, readerAuthPrivateKey, readerAuthenticationStructure)
6 val certItem=CborBuilder().add(x509Certificate).build().firstOrNull()
7 return ReaderAuthSign(signature = signatureBytes,x509Certificate = certItem)
8 }

c. List of required resources e.g cert, keys. at Integrator side.

  1. Reader private key to sign the Reader Auth structure. the resulting signature and algorithm used to sign shall be included within the mdoc request to be sent to mdoc.
  2. Reade Signer certificate containing the corresponding public key of the private key used in #a; which shall be sent to mdoc within the mdoc request. Integrator would submit a CSR to a valid CA to get a signer certificate.
  3. Reader CA certificate from CA which shall be shared by Reader to mDoc Holder which they can uses for signer certificate trust path validation

** Sample code for multiReqCallback **

Kotlin
1val multiResCallback = object : MultiResponseCallback<ResponseItem?> {
2 override fun onMultiResponse(
3 response: ResponseItem?,
4 requestCallback: MultiRequestCallback
5 ): Boolean {
6 /*
7 * 1. process the `response` and analyse or display if needed
8 * 2. check if new request is required to send: y/n
9 * - if y. create a new request using ApiConfigs.MIDRequestBuilder() and send back using
10 * `requestCallback.onNextRequest()`
11 * - if n, return false and wait for onSuccess or onError with final response
12 */
13 handleMultiResponse(response,requestCallback)
14 return true
15 }
16
17 }

Sample code for setCrlDownloaderCallback [optional].

Kotlin
1/**
2* Use this setter `setCrlDownloaderCallback` to configure the callback for CRL downloading via application side and return to verifySDK.
3 *
4* @param crlDownloaderCallback callback to be used by verifySDK to pass CRL distribution point URL(s) and return the downloaded crl data back to verifySDK.
5 * Default it is set to null if not set by app / integrator - which means verifySDK shall only check the CRL loaded from Vical only (if present).
6* @param forceDownload when true- verifySDK to ignore already available crl from vical (if present) and use crlDownloaderCallback to get it downloaded via ap; dafault is false.
7* @param timeoutInMillis - verifySDK waits for app to download and return the crl data, default timeout is DEFAULT_CLR_DOWNLOAD_TIMEOUT=3 seconds
8* till this timeout else skips crl check and assumes certificate as NOT Revoked.
9*/
10
11fun setCrlDownloaderCallback(crlDownloaderCallback: CRLDownloaderCallback?=null,
12 forceDownload:Boolean=false,
13 timeoutInMillis:Long=DEFAULT_CLR_DOWNLOAD_TIMEOUT)
  • Here are the steps to follow by application integrator to use above callback:

Step1. Declare and implement the callback object

Kotlin
1protected val crlCheckCallback=object: CRLDownloaderCallback {
2 override fun doDownload(crlDpUrlList: List<String>): CrlDownloaded? {
3 val completableFuture = CompletableFuture<CrlDownloaded>()
4 // check if same CRL is already download within last 24 hours or as per the timeout managed
5 //if timeout is reached or exceeded; clean the cache and return null or empty in `crlFromCache`
6 val crlFromCache=loadFromCache(crlDpUrlList)
7 if(crlFromCache?.isNotEmpty() == true){
8 completableFuture.complete(CrlDownloaded(crlFromCache))
9 return completableFuture.get()
10 }
11 if(!AppUtils.isInternetConnected(this@BlinkIDScanActivity)){
12 logAny("$crlCheckTag Connectivity error:Could not download CRL from remote, return null")
13 return null
14 }
15 //else download from remote and return
16 lifecycleScope.launch {
17 try {
18 //Download the same the data and download time in cache
19 val downloadedCrls = DownloadManager(this@BlinkIDScanActivity).downloadCrlDataList(crlDpUrlList)
20 completableFuture.complete(CrlDownloaded(downloadedCrls))
21 } catch (e: Exception) {
22 logAny("$crlCheckTag CRL Downloaded failed due to an exception:${e.message}, return null")
23 completableFuture.completeExceptionally(e)
24 }
25 }
26
27 return completableFuture.get()
28 }
29
30 }

Step 2. Set the callback in request configuration model similar to setReaderAuthCallback

Kotlin
1val timeoutConfig=5000L
2 val isForceDownloadConfig=true // true indicates ignore the crl received from Vical and use the downloaded one
3 val apiConfigs = ApiConfigs.MIDRequestBuilder()
4 .version("1.0")
5 .addDocType("<tocType>").apply {
6 addParams(<paramsList>)
7 }.buildDoc()
8 .addDocType("<tocType2>").apply { // configure another docType
9 addParams(<paramsList2>)
10 }.buildDoc()
11
12 .setReaderAuthCallback(readerAuthSignerCallback,readerAuthAlgorithm)
13 .setCrlDownloaderCallback(crlDownloaderCallback, forceDownload = isForceDownloadConfig,timeoutConfig)
14 .build()

  1. Obtain the response callback for parsing the engagement QR code data scan as shown in the snippet:
Kotlin
1/**
2 * Request callback for sendRequest SDK api to receive and display response data from Mobile ID
3 */
4 val mRequestCallback = object : RequestCallback<ResponseItem?, ProgressItem> {
5
6 override fun onSuccess(response: ResponseItem?) {
7 Log.e(TAG, "Mobile ID response:$response")
8 displayResponse(response as DLDataModel)
9 }
10
11 override fun onError(error: IError?) {
12 handleError(error = error as VSDKError)
13 }
14
15 override fun onProgress(progress: ProgressItem) {
16 Log.e(TAG, progress.toString())
17 }
18
19 }
  1. You can cancel/terminate a transaction any time if an error occurs in the app, or if the user cancels the transaction by tapping the Back button. Cancel a transaction by calling the terminateSession() method as shown in the snippet:
Kotlin
1mIdVerify?.terminateSession()

7.1. In order to close a running connection and start another connection using prepareConnection use terminateConnection API

Kotlin
1mIdVerify?.terminateConnection()

Integrate NFC Handover + BLE/NFC/WiFi Use case 

  1. Initialise NFC device Engagement
Kotlin
1val apiConfigs = ApiConfigs.Builder()
2 .withConfigs().apply {
3 useNfcHandover()
4 //setBLEMacAddress(bleMacAddress) for mac address connect use this option
5 setNfcConfigs(NfcConfigs.Builder().setPresenceCheckDelay(1000)
6 .addNfcDetectCallback(object:NfcConfigs.NfcDetectCallback{
7 override fun onTagDiscovered(tag: Tag?): Boolean {
8 // indicates new nfc tag is discovered. return true to process the tag
9 // you may add / display some progress indicator for user
10 // once the handover is done, feedback will be received in mDEParserCallback
11 return true
12 }
13 })
14 .build())
15 //...
16 }.buildConfigs()
17 .build()
18 mIdVerify?.initDeviceEngagement(apiConfigs, mDEParserCallback)
  1. After device engagement is complete, follow the same steps as described above

  2. To configure NFC or Wifi as data transfer method add configs in ConnectionConfigs Builder.

Kotlin
1val connectionConfigs = ConnectionConfigs.Builder()
2 .withConfigs().apply {
3 setResponseTimeout(10000) //sdk will disconnect and return with error code 303 if transaction doesn't complete in 10 seconds
4 setConnectTimeout(10000) //sdk will return with error code 206 is connection not established withing 10 seconds
5 useNfc() // or useWifi() // or connectAsmDocPeripheral() or connectAsmDocCentral
6 }.buildConf()
7 .build()

Note:

  • By default BLE mDoc Central mode is the preferred mode if multiple modes are available from mDL holder
  • From Reader side verify SDK allows the integrator to configure the preferred connection mode, however if configured mode is not available, VerifySDK will try to connect using whichever mode is available with mDL holder

Request Parameters 

The following table provides a list of attributes which can be configured for sendRequest API.

Item#
Identifier
Param Name
CBOR Type
Namespace= "org.iso.18013.5.1"
1ADMINISTRATIVE_NUMBERadministrative_numberMajor type 3
2SEXsexMajor type 3
3HEIGHTheightMajor type 0
4WEIGHTweightMajor type 0
5EYE_COLOReye_colorMajor type 3
6HAIR_COLORhair_colorMajor type 3
7BIRTH_PLACEbirthplaceMajor type 3
8RESIDENT_ADDRESSresident_addressMajor type 3
9PORTRAIT_CAPTURE_DATEportrait_capture_dateTag value 0 of major type 6
10AGE_IN_YEARSage_in_yearsMajor type 0
11AGE_BIRTH_YEARage_birth_yearMajor type 0
12AGE_OVER_NNage_over_NNValue 20/21 of major type 7
13ISSUING_JURISDICTIONissuing_jurisdictionajor Type 3
14NATIONALITYnationalityMajor type 3
15RESIDENT_CITYresident_cityMajor type 3
16RESIDENT_STATEresident_stateMajor type 3
17RESIDENT_POSTAL_CODEresident_postal_codeMajor type 3
18BIOMETRIC_TEMPLATE_XXbiometric_template_xxMajor type 2
19NAME_NAT_CHARname_nat_charMajor type 3
20MGMT_NEXT_UPDATEmgmt_nextupdateTag value 0 of major type 6
21FAMILY_NAMEfamily_nameMajor type 3
22GIVEN_NAMEgiven_nameTag value 0 of major type 6
23BIRTHDATEbirthdateTag value 0 of major type 6
24ISSUE_DATEissue_dateTag value 0 of major type 6
25EXPIRY_DATEexpiry_dateMajor type 3
26ISSUING_COUNTRYissuing_countryMajor type 3
27ISSUING_AUTHORITYissuing_authorityMajor type 3
28DOCUMENT_NUMBERdocument_numberMajor type 3
29PORTRAITportraitMajor type 2
30MGMT_LAST_UPDATEmgmt_lastupdateTag value 0 of major type 6
31MGMT_VALIDITYmgmt_validityTag value 0 of major type 6
32ONLINE_TOKEN_XXXXonline_token_xxxxMajor type 3
34DRIVING_PRIVILEGESdriving_privilegesMajor type 4
35SIGNATURE_USUAL_MARKsignature_usual_markMajor type 3
36ONLINE_URL_XXXXonline_url_xxxxMajor type 3
37BIRTHDATEbirth_dateMajor type 3
38BIRTH_PLACEbirth_placeMajor type 3
39NAME_NAT_CHARname_national_characterMajor type 3
40FAMILY_NAME_NATIONAL_CHARfamily_name_national_characterMajor type 3 //added in N19xx
41GIVEN_NAME_NATIONAL_CHARgiven_name_national_characterMajor type 3 //added in N19xx
Namespace= "org.iso.18013.5.1.aamva"//based on mDL-Implementation-Guidelines-1-0_2021.pdf
1DOMESTIC_DRIVING_PRIVILEGESdomestic_driving_privilegesMajor type 3
2DHS_COMPLIANCEDHS_complianceMajor type 3
3NAME_SUFFIXname_suffixMajor type 3
4ORGAN_DONORorgan_donorMajor type 0
5VETERANveteranMajor type 0
6FAMILY_NAME_TRUNCATIONfamily_name_truncationMajor type 3
7GIVEN_NAME_TRUNCATIONgiven_name_truncationMajor type 3
8AKA_FAMILY_NAME_V2aka_family_name.v2Major type 3
9AKA_GIVEN_NAME_V2aka_given_name.v2Major type 3
10AKA_SUFFIXaka_suffixMajor type 3
11WEIGHT_RANGEweight_rangeMajor type 0
12RACE_ETHNICITYrace_ethnicityMajor type 3
13EDL_CREDENTIALEDL_credentialMajor type 0
14SEXsexMajor type 0
15RESIDENT_COUNTYresident_countyMajor type 3
16HAZMAT_ENDORSEMENT_EXPIRATION_DATEhazmat_endorsement_expiration_dateMajor type 3
17DHS_TEMPORARY_LAWFUL_STATUSDHS_temporary_lawful_statusMajor type 0

Expected Results 

QR code

Below are expected response from the sendRequest API with the expected data type.

Data Fields
Data type/Unit
Sample Value
Namespace= "org.iso.18013.5.1"
administrative_numberText/String"1234453"
genderText/String"M"
heightInteger/Centimeter"157"
weightInteger/Kg"56"
eye_colorText/String"BLU"
hair_colorText/String"BLACK"
birthplaceText/String"NY"
resident_addressText/String"123, ABC Street"
portrait_capture_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
age_in_yearsInteger/String"34"
age_birth_yearInteger/String"1978"
age_over_NNBoolean/String"true"
issuing_jurisdictionText/String"NY"
nationalityText/String"US"
resident_cityText/String"NY"
resident_stateText/String"NY"
resident_postal_codeText/String"58773"
name_nat_charText/String"US"
mgmt_nextupdateDateTime/RFC3339"1985-04-12T23:20:50Z"
family_nameText/String"Sample"
given_nameText/String"Joe"
birthdateDateTime/RFC3339"1985-04-12T23:20:50Z"
issue_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
expiry_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
issuing_countryText/String"US"
issuing_authorityText/String"NY"
document_numberInt/String"782593823"
portraitByteArray/Bytes
mgmt_lastupdateDateTime/RFC3339"1985-04-12T23:20:50Z"
mgmt_validityDateTime/RFC3339"1985-04-12T23:20:50Z"
driving_privilegesText/String[{"codes": [{"sign": "Sign","value": "value","code": "C"}],"issue_date": "2018-08-09","vehicle_category_code": "A","expiry_date": "2024-06-11"}]
RealIDBoolean/Stringtrue
signature_usual_markByteArray/Bytes
birth_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
birth_placeText/String"NY"
name_national_characterText/String"US"
given_name_national_characterText/String"US"
family_name_national_characterText/String"US"
Namespace = "org.iso.18013.1.aamva"
DHS_complianceText/String“F” = fully compliant “N” = non-compliant
domestic_driving_privilegesText/String[{"domestic_vehicle_class": {"expiry_date": 0("2035-10-12 07:20:50.52Z"), "issuer_date": 0("2019-10-12 07:20:50.52Z"), "domestic_vehicle_class_code": "A", "domestic_vehicle_class_description": "vehicle category description"}, "domestic_vehicle_endorsements": [{"domestic_vehicle_endorsement_code": "E", "domestic_vehicle_endorsement_description": "vehicle endorsement description"}], "domestic_vehicle_restrictions": [{"domestic_vehicle_restriction_code": "C", "domestic_vehicle_restriction_description": "vehicle restrictions description"}]}]
name_suffixText/String“SR”
organ_donorInteger1
veteranInteger1
family_name_truncationText/String“N”
given_name_truncationText/String“N”
aka_family_name.v2Text/String“N”
aka_given_name.v2Text/String“S”
aka_suffixText/String“N”
weight_rangeInteger“3” //Indicates the approxi- mate weight range of the credential holder: 0 = up to 31 kg; 1 = 32 – 45 kg ; 2 = 46 - 59 kg ; 3 = 60 - 70 kg
race_ethnicityText/String“A” //Codes for race or eth- nicity of the creden- tial holder, as defined in AAMVA D20.
EDL_credentialInteger1 //This field is either absent or has one of the following values: 1: Driver’s license, 2: Identification card (Applicable only in the US. )
sexInteger1
resident_countyText/String"107" //The 3-digit county code of the county where the credential holder lives, as per the 2010 FIPS Codes for Counties and County Equivalent Entitiesf. (Applicable only in the US. )
hazmat_endorsement_expiration_dateText/String"2024-01-11"
DHS_temporary_lawful_statusInteger1 // This field is either absent or has value= 1: Temporary lawful status (Applicable only in the US. )

Deprecations and Deletions 

  • Deprecated APIs/Methods/Properties from previous versions are removed

ProGuard Rules 

The following code snippets should be added in the app ProGuard Rules file.

  • SDK obfuscation rules:
Language not specified
1-keep public class idemia.verify.sdk.** {
2 public protected *;
3}
4-keep class org.bouncycastle.**{*;}

Release Notes 

  • Refer CHANGELOG.md for full release notes history.

IACA certificate file format support 

  • Supports following formats for IACA certificates - (.pem, .crt, .der).

Elliptic Curve Support 

Operation
Curve
Specification
Curve Identifier
ECDH/ECDSAP-256FIPS-PUB 186-4IANA COSE Registry
ECDH/ECDSAP-384FIPS-PUB 186-4IANA COSE Registry
ECDH/ECDSAP-521FIPS-PUB 186-4IANA COSE Registry
ECDH/ECDSAbrainpoolP521r1RFC 5639IANA COSE Registry
ECDH/ECDSAbrainpoolP320r1RFC 5639IANA COSE Registry
ECDH/ECDSAbrainpoolP384r1RFC 5639IANA COSE Registry
ECDH/ECDSAbrainpoolP512r1RFC 5639IANA COSE Registry
ECDHX25519RFC 7748IANA COSE Registry
ECDHX448RFC 7748IANA COSE Registry
EdDSAEd25519RFC 8032IANA COSE Registry
EdDSAEd448RFC 8032IANA COSE Registry

ISO-18013-5 Specification Support 

ISO Version
Supported
N2448 (v1.1 Draft7)Yes
N1985 (published 1.0)Yes
N1938Yes
N1818Yes
N1677Yes

Additions & Updates 

  • ISO Amendments N2448 (v1.1 Draft7):
    • Device engagement implementation for with backwards compatibility support
    • NFC Static+L2cap PSM functionality for mdoc Peripheral mode
    • NFC Negotiated+L2cap PSM functionality for mdoc Peripheral mode
    • NFC Negotiated+L2cap PSM functionality for mdoc Central mode
    • ReaderAuthAll Implementation for N2448
  • Implemented callback for downloading CRL data from the integrators application
  • Compatible with Android 15 Beta (API level 35)
  • Bug fixes and improvements

Error Codes 

Error Code
Error Code Message
Description
Action Required
101Invalid QR CodeUnable to scan the QR code.Please try again.
102QR code parsing errorUnable to find some elements in the QR data item, Try again.Try Again
103QR code parsing errorDataItem(Map) is not found or empty, Unable to parse the QR code that the Mobile ID has provided.Try again
104QR code parsing errorDataItem(Array) not found or empty, Unable to parse the QR code that the Mobile ID has provided.Try again
105QR code scan errorUnable to Scan QR code may be because of invalid data or bad encodingTry Again
109Invalid cipher suiteOnly cipher suite 1 (EC algorithm) is supported.Try Again
110Invalid EDeviceKeymdoc ephemeral public point in the EDeviceKey in the DeviceEngagement structure sent by the mdoc is not on the indicated curve.Try Again
111Invalid EDeviceKeyIncorrect or unspecified curve Id, key type (kty) or x,y coordinates received in EDeviceKey DeviceEngagement structure sent by the mdocTry Again
123Image Conversion ErrorError in convert image from bitmap to ImageTry again.
141Nfc engagement errorInvalid NFC Tag, unable to read dataTry again
142NFC handover errorIncorrect types for ac record,carrier record and auxiliary recordTry Again
143NFC handover errorReference length indicated longer than available bytes.Try again
144NFC handover errorTag was lost, error during APDU transmission, tag may be out of field.Try Again
145ISO-DEP is not supportedMain Tag is not supporting ISO-DEP technology.Try again
146NFC handover errorError with TT4 configurationTry again
147NFC handover errorWrongly formatted Service Parameter recordTry again
148NFC handover errorError with Carrier Configuration record linkingTry again
149NFC handover errorMain Initial message is null.Try again
150Nfc error - bad contextBad context supplied - must be an Activity contextPass the activity context in VSDKConfigs(activity) while creating VerifySDK Object, and try again
151Nfc error - not enabledNFC is not enabled. Go to settings and enable NFCYou may call VIDUtils.promptNfcSettings() to launch the NFC setting page or enable manually from setting
152Nfc handover errorError in NFC Handover, while getting NDEF TAG
201Unable to initialize BLEError in initializing BLE feature of this device.The Mobile ID reader is not able to get BLE. The Mobile ID reader may abort the transaction.
202Device Doesn't Support BLEThis device doesn't support the BLE feature.The Mobile ID reader is not able to get BLE. The Mobile ID reader may abort the transaction.
203BLE Scanning ErrorScanning of the BLE devices failed.The Mobile ID reader is not able to scan the BLE devices. The Mobile ID reader may abort the transaction.
204BLE connection ErrorThis device's Bluetooth is off.The Bluetooth of the device is not enabled. The Mobile ID reader may abort the transaction.
205BLE Scanning ErrorPlease provide the BLUETOOTH permissionsTry again
206Connection TimeoutUnable to create communication channel with mDL deviceTry again
207BLE connection ErrorAn unexpected value exchanged during transmissionTry again
208BLE Advertising ErrorFailed to add BLE serviceTry again
209BLE L2CAP ErrorError while receiving response from mIDTry again
210BLE L2CAP ErrorError while transferring request to mIDTry again
212BLE Connection ErrorError in BLE state due to previous/indisposed connection(s)
221Connection mode not availableVerifySDK is not able to setup connection with Mobile ID using configured connection type/mode.Try again
281BLE Permission ErrorRequired permission BLUETOOTH_ADMIN not found in app AndroidManifest.xml
282Location Permission ErrorRequired permissions ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION not found in app AndroidManifest.xmlPlease declare the required permissions in your app AndroidManifest.xml
283Location Permission ErrorRequired permission ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION not grantedUser must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissionsr
284BLE Permission errorRequired permission BLUETOOTH_CONNECT not found in app AndroidManifest.xmlandroid.permission.BLUETOOTH_CONNECT permission should be added in your app AndroidManifest.xml
285BLE Permission errorRequired permission BLUETOOTH_CONNECT not grantedUser must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions
286BLE Permission errorRequired permission BLUETOOTH_SCAN not found in app AndroidManifest.xmlandroid.permission.BLUETOOTH_SCAN permission should be added in your app AndroidManifest.xml
287BLE Permission errorRequired permission BLUETOOTH_SCAN not grantedUser must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions
288BLE Permission errorRequired permission BLUETOOTH_ADVERTISE not found in app AndroidManifest.xmlandroid.permission.BLUETOOTH_ADVERTISE permission should be added in your app AndroidManifest.xml
289BLE Permission errorRequired permission BLUETOOTH_ADVERTISE not grantedUser must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions
290Error in connectionCan't create connection without device engagement.initDeviceEngagement should be called before calling PrepareConnection
291Error in connectionConnection terminated by client.Call prepareConnection API to create new connection
292Error in connectionCan't send request without prepareConnection.prepareConnection api should be called before sendRequest
301Transaction CancelledTransaction has been cancelled or closed.Connection closed due to an error, try again.
302Connection LostUnfortunately has device disconnected; device may be out of BLE/NaN.NFC rangeThe Mobile ID reader may abort the transaction. Try Again
303Timed Out, Try againTransaction has timeout or cancelledTry Again
304Request Incomplete.Please select one or more attributes to be included in the request to the Mobile IDTry Again
305Incomplete RequestAn Mobile ID comes to an end of data when expecting more data. For example, an Mobile ID expects certain length, number of arrays elements, or map entries but instead encounters the end of the data. The Mobile ID does not return any data but the error message.The Mobile ID reader may abort the transaction.
306Request RejectedThe Mobile ID indicates that the request is rejected.BLE connection failure. he Mobile ID reader may abort the transaction.
307The Mobile ID Reader Authentication ErrorThe Mobile ID indicates there is an error with Mobile ID Reader authenticationTry Again
308General ErrorThe Mobile ID returns an error without any given reason.The Mobile ID reader may inspect the request, ensure request is complete, and resend. The Mobile ID reader may abort the transaction.
309Invalid RequestRequest can't contain more than 2 age_over_nn as request attributesTry Again
310Error in reader authenticationcallback or algorithm can not be null or emptyTry Again
311Error in request dataRequest params are null or invalid; Can't proceedTry Again
312Session Terminated by mDocSessionData status 20 is received from mDocTry Again
400Error in response data received.Response data is malformed or nilTry Again
401Parsing ErrorAn Mobile ID encountered data element that is not well-formed (e.g., invalid initial=byte) and failed decoding data. The Mobile ID does not return any data but the error message.The Mobile ID reader may inspect the request, ensure request is complete, and resend. The Mobile ID reader may abort the transaction.
402Invalid FormatThe Mobile ID cannot process the requested data element due to a formatting error.Try Again
403Data Not FoundThe requested NameSpace or data element within a NameSpace is not found.Try Again
404Data Request DeniedThe release of requested data element was rejected by the Mobile ID holder.Try Again
405Data Not ReturnedThe Mobile ID does not provide the requested data element without any given reason.Try Again
406CBOR decoding ErrorThe Mobile ID indicates an error during CBOR decoding that the data received is not valid CBORTry Again
407CBOR Validation ErrorThe Mobile ID indicates an error during CBOR validation, e.g. wrong CBOR structuresTry Again
451Certificate Path ErrorEither Path is invalid or inaccessible or not a folder path or folder is emptyProvide valid path and check required permissions to read/write the files are granted by user
482IACA-DS validation ErrorIACA-DS validation Error::Transaction not authenticated due to non-compliant or invalid DS or IACA certificateTry Again!
483Vical Loading ErrorError while loading vical file: [vicalFileName].Try Again!
484License Authentication FailureVical file [vicalFileName] can’t be authenticated using given certificate: [vicalFileCertificate].Try Again!
500Generic ErrorGeneric Error from VerifyID abstraction layer, concrete class must override to throw actual errorTry Again
701Unable to discover Wi-Fi Aware serviceWi-Fi Aware Service is not discovered.Try Again
702Device Doesn't Support WifiThis device does not support wifi feature.Try Again
703Wifi Aware Connection TimeoutUnable to establish socket connection, try again.Try Again
704WIFI is OFFThis device Wi-Fi is disabled, enable WiFi and try again.Try Again
705WiFi aware Network is LostWifi aware connection network lost, try againTry Again
706Error in WiFi communicationIncorrect HTTP status code, expected 200 but found other.Try Again
751NFC data transfer error.The Mobile ID Request is null or malformedTry Again
752NFC data transfer errorResponse data is null or malformed, try again.Try Again
753NFC connection errorISODep not connected; make sure to tap on back of other device to setup the NFC connection.Try Again
754NFC data transfer errorError in receiving response from The Mobile ID, try again.Try Again
755NFC data transfer errorError in NFC data transfer service, try again.Try Again
756NFC connection errorNFC hardware is disabled, Enable NFC from settings and try again.Try Again
757NFC connection errorNFC not supported as a system feature.Try transfer mode other than NFC
758NFC data transfer errorTag was lost;Error during APDU NFC data transfer transmission,tag may be out of field
802Network ErrorNo internet connection available.Please turn on your internet connection and Try Again!No internet connection available.Please turn on your internet connection and Try Again!
801License Validation FailureSome of the arguments are not right.Please check the arguments and Try Again!Some of the arguments are not right.Please check the arguments and Try Again!
803Network ErrorNetwork connection lost while fetching data.Please check your internet connection and Try Again!Network connection lost while fetching data.Please check your internet connection and Try Again!
804Request Validation FailureRequest validation problem.Please check your request and Try Again!Request validation problem.Please check your request and Try Again!
805Server ErrorServer error. Please wait for sometime!License Server error.Please wait for sometime!
806Bad ConfigurationsError generating activation data on the server perhaps bad configuration.Please check your configurations and Try Again!Error generating activation data on the server perhaps bad configuration.Please check your configurations and Try Again!
807Bad ConfigurationsThe specified resource is not available profile or apikey or both are invalid or that an unknown service exception happened.Try Again!The specified resource is not available profile or apikey or both are invalid or that an unknown service exception happened.Try Again!
808License ExpiredYour license is expired.Please renew your license and Try Again!Your license is expired.Please renew your license and Try Again!
809License Validation FailureError while fetching data. License generic exception.Try Again!Error while fetching data.License generic exception.Try Again!

Test Samples 

QR + BLE Sample 

The following screen shows a scan of the QR code in the Mobile ID App.

Note: This screenshot is only for device engagement QR code testing. The full QR + BLE scenario will only work with a real device with the IDEMIA Mobile ID App installed.