Android Beginners Guide
Intro sentence
This guide is for developers and integrators who want to integrate the DC SDK into an Android application.
Overview
DC SDK is a modular identity platform for Android apps. It provides the building blocks to:
- onboard users through identity enrollment,
- issue and manage credentials in an on-device wallet,
- handle online authentication and request-driven flows,
- share identity attributes in person (ISO 18013 scenarios),
- maintain credential trust over time with update and lifecycle operations.
1. Get Started
Prerequisites
Before integrating the SDK, make sure your development environment meets the following requirements.
Supported CPU architectures (required by the Capture SDK):
armeabi-v7a(32-bit ARM devices)arm64-v8a(64-bit ARM devices)
NOTE: The SDK does not support x86/x64 architecture. Android Emulators on Intel-based machines are not supported. A physical Android device is required. Emulators running on Apple Silicon (M-series Macs) works due to ARM64 compatibility.
Skills Required
You must have working knowledge of:
- Android Studio
- Kotlin
- Android SDK
- Maven/Gradle dependency management
- Kotlin Coroutines
Resources Required
Android integration may be performed on macOS, Linux, or Windows with the following tools:
- Android Studio
- JDK: preferred the latest version (17 or above) — Android Studio includes a bundled JDK
- Android SDK tools: preferred the latest version (API level 29 or above)
- Minimum Android SDK version: 29 (Android 10.0)
- Physical Android device (emulator is not supported)
Access to Artifactory
SDK artefacts are published to a dedicated Maven repository. You will need:
- Access credentials (
artifactoryUser/artifactoryPassword) — provided together with the licenses and SDK configuration file - Access to SDK dependencies - available from Artifactory
- Access to the sample app:
mobileid-sdk-sample-app-XX.XX.XX.zip— available from Artifactory - Access to SDK KDoc:
sdk-api-kdoc-XX.XX.XX.zip- available from Artifactory
Sample Application
A Sample Application is available alongside the SDK package. It demonstrates the recommended SDK integration flow, provides examples of using the SDK APIs, and can be used to validate the configuration provided for your environment.
The Sample Application also allows you to explore and test features available through the Digital Credentials Platform before integrating them into your own application.
2. Project Configuration
Before configuring your project manually, it is recommended to download the sample app from Artifactory and import it into Android Studio. The sample app contains the most up-to-date working configuration as a reference.
Credentials DC repositories
Define in your ~/.gradle/gradle.properties following properties credentials to required repositories
Properties1mobileIdArtifactoryUser=2mobileIdArtifactoryPassword=3artifactoryUserMI=4artifactoryPasswordMI=
Repositories required to build DC SDK and Sample App are defined in gradle.properites.
Properties1idemiaRepositoryUrl=2remoteRepositoryUrl=3mobileIdSdkRepositoryUrl=
NOTE: The username and password are provided together with the licenses and SDK configuration file.
Dependencies
Add the required SDK dependencies in your application build.gradle file. Repository URLs and exact version numbers are available in the sample app (mobileid-sdk-sample-app/app/build.gradle).
Groovy1dependencies {2 // sdk api library3 implementation "com.idemia.mid.sdk:sdk-api:${Versions.mobileIdSdkVersion}"4 implementation "com.idemia.mid.sdk:unlock:${Versions.mobileIdSdkVersion}"5 implementation "com.idemia.mid.sdk:remote-face-liveness-plugin:${Versions.idemiaMobileIdSdkVersion}"6 implementation "com.idemia.mid.sdk:document-capture-plugin:${Versions.idemiaMobileIdSdkVersion}"78 // Kotlin Coroutines9 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}"10 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}"11}
NOTE: The SDK does not support app data backup after uninstall. If you generate a new project from Android Studio, it adds
android:allowBackup="true"to theapplicationtag by default. You must either remove this attribute or explicitly set it tofalse.
App Name
The SDK requires the integrator to provide the application name via the R.string.app_name string resource:
XML1<string name="app_name">Your App Name</string>
This value is used by the SDK in the following ways:
- As part of the
User-Agentheader sent to backend services:Language not specified1User-Agent: Your App Name/XX.XX.XX SDK/XX.XX.XX Android - To customize messages shown to the end user, for example on error screens.
3. SDK Integration
Overview
The SDK must be initialized during application startup before any SDK APIs can be accessed. The recommended approach is to perform initialization from a custom Application class and expose a shared MobileIDHolder instance for the rest of the application.
Terminology
Term | Description |
|---|---|
MobileID | The main SDK API used by the application. |
MobileIDProvider | Factory responsible for creating a MobileID instance. |
MobileIDHolder | Lifecycle-aware container that manages SDK initialization and provides access to the initialized MobileID instance. This is an example code to initialize MobileID |
MobileIDConfiguration | Configuration object containing all SDK settings and backend information. |
Tracker | Optional analytics interface used to receive SDK events. |
Prerequisites
Before initializing the SDK, ensure that:
- The SDK dependencies are added to your project.
- A valid SDK configuration is available
- Sample Application was build with the configuration
- Sample Applicaiton was launched on your phone
1. Create a Custom Application Class
Create a custom Application class responsible for SDK initialization.
Kotlin1class MyApplication : Application(), MobileIDHolderProvider, CoroutineScope by CoroutineScope(Dispatchers.IO) {23 private val configuration = MobileIDConfiguration()4 private lateinit var mobileIDHolder: MobileIDHolder56 override fun getMobileIDHolder(): MobileIDHolder = mobileIDHolder78 override fun onCreate() {9 super.onCreate()1011 val mobileIDProvider = createMobileIdProvider()12 registerActivityLifecycleCallbacks(MyActivityLifecycleCallbacks())13 mobileIDHolder = MobileIDHolder(14 application = this,15 mobileIDProvider = mobileIDProvider16 )1718 launch {19 mobileIDHolder.createMobileId()20 }21 }2223 private fun createMobileIdProvider(): MobileIDProvider {24 val configuration : MobileIDConfiguration = ConfigurationProvider().get()2526 return MobileID.initialize(27 application = this,28 configuration = configuration,29 analyticsTracker = MyTracker(),30 analyticsOptOut = false31 )32 }33}
2. SDK Configuration
Provide the configuration before initializing the SDK.
There are two approaches to provide configuration. The first is creating an instance of MobileIDConfiguration, fill out all properties and this is recommended. Another is to load for example Json file from assets. This approach you will find in Sample App but it is not recommended and it is used just only for presentation. In general you should receive all properties from us to fill out configuration. To get more info about configuration file, you can download sdk-api-kdoc-${version}.zip file from artifactory and find out its KDoc.
Kotlin1val configuration = ConfigurationProvider().get()
Security Recommendation
We strongly recommend creating the
MobileIDConfigurationobject programmatically rather than loading it from application assets or resources.The configuration contains backend endpoints and API keys used to communicate with Digital Credential services. Resource and asset files can be easily extracted from a packaged APK. While tools such as R8 provide code obfuscation, they do not protect static configuration files.
For production deployments, store configuration values in application code and apply standard Android code obfuscation and hardening techniques.
3. Initialize MobileID
Create a MobileIDProvider using the MobileID.initialize() API.
Kotlin1val mobileIDProvider = MobileID.initialize(2 application = this,3 configuration = configuration,4 analyticsTracker = FirebaseTracker(Firebase.analytics),5 analyticsOptOut = false6)
Parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
application | Application | Yes | The Android Application instance. |
configuration | MobileIDConfiguration | Yes | The SDK configuration object delivered in the SDK package. Do not modify values other than colors and appInfo. |
analyticsTracker | Tracker? | No | An optional implementation of the Tracker interface. Provide this to receive and handle SDK analytics events in your app. |
analyticsOptOut | Boolean | No | Set to true to opt the user out of analytics tracking. Defaults to false. |
NOTE: Code examples are available in
mid-sdk-sample-app— seeSplashScreenActivity.
4. Register Activity Lifecycle Callbacks
Register the provided activity lifecycle callbacks to allow the SDK to observe Android activity state changes and create MobileID instance if previous attempts failed.
Kotlin1registerActivityLifecycleCallbacks(MyActivityLifecycleCallbacks())23// where45class MyActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks, CoroutineScope by CoroutineScope(Dispatchers.IO) {67 override fun onActivityStarted(activity: Activity) {8 if (activity is MobileIDInitializationFailed) {9 return10 }1112 val mobileIDHolder = activity.mobileIDHolder()13 launch {14 if (mobileIDHolder.getMobileIDState() == MobileIDState.NotInitialized) {15 mobileIDHolder.createMobileId()16 }17 }18 }19 ...20}
5. Create a MobileIDHolder
Creating a MobileID instance involves remote configuration download and SDK initialization, which are asynchronous operations. MobileIDHolder acts as a lifecycle-aware container that:
- Maintains the initialization state.
- Exposes the initialized
MobileIDinstance. - Allows consumers to wait until initialization is completed.
- Recovers from initialization failures.
Kotlin1mobileIDHolder = MobileIDHolder(application = this, mobileIDProvider = mobileIDProvider)
6. Create the MobileID Instance
Initialize MobileID asynchronously on a background thread.
Kotlin1launch {2 mobileIDHolder.createMobileId()3}
This ensures that SDK initialization does not block the application's main thread.
7. Expose the MobileIDHolder
Implement the MobileIDHolderProvider interface to provide global access to the SDK holder.
Kotlin1interface MobileIDHolderProvider {2 fun getMobileIDHolder(): MobileIDHolder3}
Implementation:
Kotlin1override fun getMobileIDHolder(): MobileIDHolder = mobileIDHolder
Usage from an Activity or Fragment:
Kotlin1suspend fun Context.mobileID(): MobileID {2 return (applicationContext as MobileIDHolderProvider).getMobileIDHolder().waitForMobileIdInitialization()3}45suspend fun Activity.mobileID(): MobileID {6 return (application as MobileIDHolderProvider).getMobileIDHolder().waitForMobileIdInitialization()7}89suspend fun Fragment.mobileID(): MobileID {10 return requireActivity().mobileID()11}
Consumers should always obtain the SDK instance through waitForMobileIdInitialization(). This method suspends until initialization completes successfully and guarantees that a valid MobileID instance is returned.
8. Using MobileID
After initialization, obtain the MobileID instance from any Android component.
Kotlin1class MainActivity : AppCompatActivity() {23 override fun onCreate(savedInstanceState: Bundle?) {4 super.onCreate(savedInstanceState)56 lifecycleScope.launch {7 val mobileID = mobileID()89 // Use MobileID APIs10 }11 }12}
9. AndroidManifest Configuration
Register the custom application class in AndroidManifest.xml.
XML1<application2 android:name=".MyApplication"3 ... />
10. Initialization Flow
Text1Application Startup2 │3 ▼4Instantiate Configuration5 │6 ▼7MobileID.initialize()8 │9 ▼10Register Lifecycle Callbacks11 │12 ▼13Create MobileIDHolder14 │15 ▼16mobileIDHolder.createMobileId()17 │18 ▼19MobileID Ready
11. Verifying the Integration
After integrating the SDK, verify that the initialization process completes successfully.
Prerequisites
- The device or emulator has an active Internet connection.
- The application starts without initialization errors.
- Logging is enabled (e.g.,
Timber.DebugTreein debug builds).
Validation Steps
- Launch the application.
- Ensure the device is connected to the Internet.
- Monitor application logs using Android Studio Logcat.
- Search for SDK log entries during startup.
Successful Initialization
The SDK is considered ready when:
- The Wallet Configuration has been downloaded.
- The
MobileIDHolderstate transitions toReady. - No initialization exceptions are reported.
MobileIDAPIs can be accessed throughwaitForMobileIdInitialization().
Expected Result
During initialization, the SDK should connect to backend services and download the Wallet Configuration.
Verify that logs do not contain entries indicating failed configuration retrieval.
Troubleshooting
If the Wallet Configuration is not downloaded:
- Verify Internet connectivity.
- Confirm the SDK configuration is correct.
- Check that the backend environment endpoints are reachable.
- Review Logcat for networking or SDK initialization errors.
- Ensure that
mobileIDHolder.createMobileId()is executed successfully.
Integration Success Criteria
A successful integration should produce the following sequence:
✅ Application starts successfully.
✅ MobileIDHolder is created.
✅ SDK initialization completes without errors.
✅ Wallet Configuration is downloaded successfully.
✅ MobileIDState transitions to Ready.
✅ Calls to waitForMobileIdInitialization() return successfully.
✅ No SDK-related exceptions are reported in Logcat.
12. Complete Example
Kotlin1class MyApplication : Application(), MobileIDHolderProvider, CoroutineScope by CoroutineScope(Dispatchers.IO) {23 private lateinit var mobileIDHolder: MobileIDHolder45 override fun getMobileIDHolder(): MobileIDHolder = mobileIDHolder67 override fun onCreate() {8 super.onCreate()910 val mobileIDProvider = createMobileIdProvider()11 registerActivityLifecycleCallbacks(MyActivityLifecycleCallbacks())12 mobileIDHolder = MobileIDHolder(13 application = this,14 mobileIDProvider = mobileIDProvider15 )1617 launch {18 mobileIDHolder.createMobileId()19 }20 }2122 private fun createMobileIdProvider(): MobileIDProvider {23 val configuration : MobileIDConfiguration = ConfigurationProvider().get()2425 return MobileID.initialize(26 application = this,27 configuration = configuration,28 analyticsTracker = MyTracker(),29 analyticsOptOut = false30 )31 }32}3334interface MobileIDHolderProvider {35 fun getMobileIDHolder() : MobileIDHolder36}3738data class MobileIDConfiguration(39 val enrollment: EnrollmentServiceConfiguration,40 val authServer: AuthServerConfiguration,41 val notifications: NotificationsConfiguration,42 val captureSdkConfiguration: CaptureSdkConfiguration,43 val appInfo: AppInfo,44 val eventEmitterConfiguration: EventEmitterConfiguration? = null,45 val walletConfiguration: WalletDownloadConfiguration? = WalletDownloadConfiguration(),46)4748interface Tracker {49 fun onScreenDisplayed(screenName: String, correlationId: String)50 fun onEvent(event: String, correlationId: String, params: Map<String, String>)51}5253class MyActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks, CoroutineScope by CoroutineScope(Dispatchers.IO) {5455 override fun onActivityStarted(activity: Activity) {56 if (activity is MobileIDInitializationFailed) {57 return58 }5960 val mobileIDHolder = activity.mobileIDHolder()61 launch {62 if (mobileIDHolder.getMobileIDState() == MobileIDState.NotInitialized) {63 mobileIDHolder.createMobileId()64 }65 }66 }67 ...68}6970class MobileIDHolder(private val context: Context, private val mobileIDProvider: MobileIDProvider) {7172 private val _instanceFlow = MutableStateFlow<MobileIDState>(MobileIDState.NotInitialized)7374 suspend fun waitForMobileIdInitialization(): MobileID = withContext(Dispatchers.Default) {75 _instanceFlow.filterIsInstance<MobileIDState.Ready>().first().mobileID76 }7778 suspend fun getMobileIDState(): MobileIDState = withContext(Dispatchers.Default) {79 _instanceFlow.first()80 }8182 suspend fun createMobileId(){83 try {84 setMobileIdState(MobileIDState.InProgress)85 val mobileID = mobileIDProvider.create()86 MobileIdEventsListeners(context, Navigator(context.applicationContext)).setupListeners(mobileID)87 setMobileIdState(MobileIDState.Ready(mobileID))88 } catch (e: Exception) {89 setMobileIdState(MobileIDState.NotInitialized)90 }91 }9293 private suspend fun setMobileIdState(mobileIDState: MobileIDState) = withContext(Dispatchers.Default) {94 _instanceFlow.emit(mobileIDState)95 }96}