This page details instructions for migrating to newer versions of the Android Welcome SDK. If you skip versions, apply every section between your current version and the target version, from oldest to newest.
Info
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
Migration to 5.54.0
1. Renamed IncodeColorPalette.positive800 to positive750
To align with Incode Studio's exported palette, positive800 has been renamed to positive750 (same color).
If you previously customized this color via Kotlin:
IncodeWelcome
.getInstance()
.setCommonConfig(
CommonConfig.Builder()
.setThemeConfig(
IncodeThemeConfig(
colorPalette = IncodeColorPalette(
positive800 = Color(0xFF0C5030)
)
)
)
.build()
)
use positive750 instead:
IncodeWelcome
.getInstance()
.setCommonConfig(
CommonConfig.Builder()
.setThemeConfig(
IncodeThemeConfig(
colorPalette = IncodeColorPalette(
positive750 = Color(0xFF0C5030)
)
)
)
.build()
)
If you provide the theme via a JSON config, rename the key inside colorPalette:
Before
{
"colorPalette": {
"positive800": "#0C5030"
}
}
After
{
"colorPalette": {
"positive750": "#0C5030"
}
}
Theme JSON that still uses the old positive800 key will silently fall back to the default, because unknown keys are ignored during parsing. Update your JSON to use positive750 to keep your customization applied.
2. The Google Wallet flow no longer lives in the ID capture screen
The Google Wallet flow moved out of the ID capture screen and into its own screen. These symbols were public only because they sat in UI classes. They are now internal or removed:
| Symbol | Change |
|---|---|
WalletIdErrorScreen |
Now internal |
InitIdCaptureUiEvent.TryAgainFromWalletError |
Removed |
IdCaptureModuleViewModel.IdCaptureStep.UploadGoogleWalletCredential |
Removed |
IdCaptureModuleViewModel.IdCaptureStep.UploadGoogleWalletError |
Removed |
IdCaptureModuleViewModel.googleWalletRequestJson |
Removed |
IdCaptureModuleViewModel.onGoogleWalletCredentialCaptured(String) |
Removed |
IdCaptureModuleViewModel.requestGoogleWallet(Activity, String) |
Removed |
All of them were undocumented, and public only by Kotlin's default visibility rather than by design. The SDK has never offered a way to place its screens in your own layout, and it provides no factory or accessor that hands out an IdCaptureModuleViewModel, so there was no supported way to reach these members. If you call any of them, remove the call.
To drive the Google Wallet flow yourself, use the non-UI mode described in Google Wallet ID. It hands you a NonUiGoogleWalletController through OnboardingListener.onGoogleWalletReady() and reports every stage on NonUiGoogleWalletListener, which replaces all of the above.
Kotlin:
// Before 5.54.0: driving the ID capture ViewModel directly.
idCaptureModuleViewModel.googleWalletRequestJson.collect { requestJson ->
val result = idCaptureModuleViewModel.requestGoogleWallet(activity, requestJson)
if (result is WalletsWrapper.Result.Success) {
idCaptureModuleViewModel.onGoogleWalletCredentialCaptured(result.credentialJson)
}
}
// 5.54.0: the SDK runs the flow and reports each stage.
object : IncodeWelcome.OnboardingListener() {
override fun onGoogleWalletReady(controller: NonUiGoogleWalletController) {
controller.start(activity, lifecycleOwner, object : NonUiGoogleWalletListener {
override fun onLoading() {}
override fun onUploading() {}
// Terminal. A rejected upload arrives here with a non-null exception: there is no SDK
// screen to retry from in this mode, so start another ID module for another attempt.
override fun onGoogleWalletCompleted(exception: IncodeException?) {}
override fun onFallback(reason: GoogleWalletFallbackReason) {}
})
}
}
Java:
// Before 5.54.0: driving the ID capture ViewModel directly.
// idCaptureModuleViewModel.getGoogleWalletRequestJson(), requestGoogleWallet(...),
// and onGoogleWalletCredentialCaptured(...) no longer exist.
// 5.54.0: the SDK runs the flow and reports each stage.
new IncodeWelcome.OnboardingListener() {
@Override
public void onGoogleWalletReady(NonUiGoogleWalletController controller) {
controller.start(activity, lifecycleOwner, new NonUiGoogleWalletListener() {
@Override public void onLoading() {}
@Override public void onUploading() {}
// Terminal. A rejected upload arrives here with a non-null exception: there is no SDK
// screen to retry from in this mode, so start another ID module for another attempt.
@Override public void onGoogleWalletCompleted(IncodeException exception) {}
@Override public void onFallback(GoogleWalletFallbackReason reason) {}
});
}
};
The document chooser behaves as it did in 5.53.0. Cancelling the credential picker returns the user to document selection, and so does Try Again on the upload-error screen, so no code change is needed there. Direct and non-UI invocation cannot offer another document type, so a rejected upload is terminal there: the ID module ends and OnboardingListener.onError() reports it. In non-UI mode it also arrives on onGoogleWalletCompleted with a non-null exception. Start another ID module if the user should try again.
Migration to 5.53.0
Migration to 5.53.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. IncodeWelcome.Builder.setGoogleWalletEnvironment(...) and GoogleWalletEnvironment have been removed
setGoogleWalletEnvironment existed to make Google Wallet requests easier to debug, but its SANDBOX/PRODUCTION naming did not reflect that purpose, so it has been replaced by IncodeWelcome.Builder.setGoogleWalletRequestSigned(Boolean), which directly controls whether the request declares the signed or unsigned protocol. If you were using GoogleWalletEnvironment.SANDBOX to exercise the unsigned protocol for debugging, use setGoogleWalletRequestSigned(false) instead.
Kotlin - before:
IncodeWelcome.Builder(application, apiUrl, apiKey)
.setGoogleWalletEnvironment(GoogleWalletEnvironment.SANDBOX)
.build()
Kotlin - after:
IncodeWelcome.Builder(application, apiUrl, apiKey)
.setGoogleWalletRequestSigned(false)
.build()
Java - before:
new IncodeWelcome.Builder(application, apiUrl, apiKey)
.setGoogleWalletEnvironment(GoogleWalletEnvironment.SANDBOX)
.build();
Java - after:
new IncodeWelcome.Builder(application, apiUrl, apiKey)
.setGoogleWalletRequestSigned(false)
.build();
2. The user-cancel analytics event is now userCanceled
The SDK reports the user-cancel event as userCanceled. Earlier versions reported it as userCancelled. The new spelling agrees with the other SDK events and with the iOS SDK.
The Event.USER_CANCELLED constant keeps its name. Only the reported string value changes. If your listener compares the Event enum, you need no change.
If you compare the string value, replace userCancelled with userCanceled:
Kotlin - before:
override fun onEvent(event: Event, eventData: HashMap<String, Any>?) {
if (event.value == "userCancelled") {
handleUserCancel()
}
}
Kotlin - after:
override fun onEvent(event: Event, eventData: HashMap<String, Any>?) {
if (event.value == "userCanceled") {
handleUserCancel()
}
}
Java - before:
@Override
public void onEvent(Event event, HashMap<String, Object> eventData) {
if ("userCancelled".equals(event.getValue())) {
handleUserCancel();
}
}
Java - after:
@Override
public void onEvent(Event event, HashMap<String, Object> eventData) {
if ("userCanceled".equals(event.getValue())) {
handleUserCancel();
}
}
Also update each dashboard query, saved report, or server-side rule that matches the literal userCancelled name.
3. Unit tests that load SQLCipher must run on JVM 17 or later
The SDK now uses net.zetetic:sqlcipher-android:4.17.0. This version makes the SDK download about 1.3 MB smaller per device, and it removes unused legacy crypto symbols from the bundled native library. It ships Java 17 bytecode.
Your Android application build is not affected. AGP 8 with JDK 17 reads the new bytecode correctly.
Your unit tests are affected if both of these are true:
- The tests run on the JVM. This includes plain JVM unit tests and Robolectric tests.
- The tests load SQLCipher classes. The tests can load them directly, or through the SDK code paths that use the encrypted database.
If those tests run on a JVM older than 17, raise the test toolchain to 17 or later:
// build.gradle of the module that runs the tests
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
Instrumented tests on a device or emulator are not affected.
4. Update the Signature V2 title and description string overrides
Signature V2 uses dedicated string resources for the title and description. V1 continues to use the existing string resources.
If you enable V2 and override the V1 strings, add these V2 overrides to your strings.xml file:
<string name="onboard_sdk_signature_capture_title">Your title</string>
<string name="onboard_sdk_signature_capture_description">Your description</string>
Keep these V1 overrides if your integration still uses V1:
<string name="onboard_sdk_signature_title">Your title</string>
<string name="onboard_sdk_signature_description">Your description</string>
No change is required if you do not override these strings. The deprecated Signature.Builder.setTitle(...) and setDescription(...) methods continue to apply to both versions.
5. Video Selfie V2 hides the close button on the camera steps
The Video Selfie V2 design hides the close (X) button on the camera steps. CommonConfig.setShowCloseButton therefore does not apply to those steps. Video Selfie V1 keeps the button over the camera.
This change applies only when you enable the V2 feature gate.
No code change is required. setShowCloseButton continues to apply to the other screens. If your users depend on the close button to leave a camera step, tell them about the new behavior, or keep Video Selfie V1.
Migration to 5.51.0
Migration to 5.51.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. Minimum Kotlin version raised to 2.2.x
The SDK is now compiled with Kotlin 2.2.21 (up from 1.9.25), to support the OkHttp/logging-interceptor 5.3.2 upgrade. Any module that compiles Kotlin source with the SDK on its classpath must be able to read the SDK's Kotlin metadata, so your project's Kotlin Gradle plugin must be 2.2.x or newer. This applies regardless of whether your code calls SDK Kotlin APIs directly - having the SDK on the classpath of a Kotlin compilation is enough to require the newer compiler. Pure-Java modules are unaffected.
No source-level API changes are required on your side - this only affects the minimum Kotlin compiler/plugin version your own build must use.
plugins {
id 'org.jetbrains.kotlin.android' version '2.2.21'
}
2. Add the required packaging exclusion for OkHttp 5.3.2's duplicate OSGi manifest
OkHttp/logging-interceptor 5.3.2's JPMS module-info jar and the JSpecify jar (a transitive dependency) both ship an identical OSGi manifest at META-INF/versions/9/OSGI-INF/MANIFEST.MF. Any app that assembles an APK with OkHttp/logging-interceptor 5.3.2 on its classpath will hit a duplicate-resource packaging error from this collision, unless that path is already excluded for another reason. This is a required step for adopting this SDK version, not a fallback for if you happen to see the error - add it to your app's build.gradle:
android {
packaging {
resources {
excludes += ['META-INF/versions/9/OSGI-INF/MANIFEST.MF']
}
}
}
This exclusion only drops the OSGi manifest (unused at runtime) and dedups any jar colliding on that path, so it also covers future additions (for example, if BouncyCastle is upgraded later and collides on the same manifest).
3. Upgrade compileSdk
With the update of the internal CameraX and Kotlin dependencies, you will need to upgrade your project's compileSdk to level 36:
compileSdk 36
4. Update Android Gradle Plugin (AGP)
Bumping compileSdk to 36 requires Android Gradle Plugin (AGP) 8.9.1 or higher.
Update your project-level build.gradle or settings.gradle file to use the new plugin version.
classpath "com.android.tools.build:gradle:8.9.1"
5. Update Gradle Wrapper
AGP 8.9.1 requires Gradle 8.14.5 or higher.
Update your Gradle wrapper configuration in gradle/wrapper/gradle-wrapper.properties:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.5-bin.zip
6. Migrate to the Kotlin Compose compiler plugin
The SDK now uses the standalone org.jetbrains.kotlin.plugin.compose Gradle plugin (introduced with Kotlin 2.x) instead of composeOptions.kotlinCompilerExtensionVersion. If your app configures Compose compilation via composeOptions, migrate to the new plugin:
Before:
android {
buildFeatures { compose = true }
composeOptions {
kotlinCompilerExtensionVersion "1.5.15"
}
}
After:
plugins {
id 'org.jetbrains.kotlin.plugin.compose' version '2.2.21'
}
android {
buildFeatures { compose = true }
// composeOptions block is no longer needed
}
7. Upgrade kotlinx-coroutines to 1.9.0
CameraX 1.6.1 requires kotlinx-coroutines 1.9.0 or higher. Upgrade your coroutines dependency to at least this version:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0'
8. Room bumped to 2.8.4
The SDK's internal local storage (Room) is upgraded from 2.6.1 to 2.8.4, to support KSP2 codegen under the Kotlin 2.2.x compiler. Room is used internally only - it is not part of the SDK's public API - so no action is required on your side.
9. deviceStats removed from Result classes that never populated it
The deviceStats field has been removed from BaseResult. It is now declared only on IdScanResult and SelfieScanResult - the only results that ever carried it. Every other *Result class (e.g. FaceMatchResult, VideoSelfieResult, EKYCResult, NfcScanResult) no longer exposes a deviceStats field.
If you read deviceStats from an IdScanResult or SelfieScanResult, no change is required. If you read it from any other result type, remove that access - those results always returned the default DeviceStats(motionStatus = Status.UNCLEAR) and never carried real device data.
Kotlin - before:
val motion = faceMatchResult.deviceStats.motionStatus // always UNCLEAR
Kotlin - after:
// deviceStats is available only on IdScanResult and SelfieScanResult
val motion = idScanResult.deviceStats.motionStatus
Java - before:
Status motion = faceMatchResult.deviceStats.getMotionStatus(); // always UNCLEAR
Java - after:
// deviceStats is available only on IdScanResult and SelfieScanResult
Status motion = idScanResult.deviceStats.getMotionStatus();
10. QES constructor is no longer public - use QES.Builder
The QES module is now constructed exclusively through QES.Builder, matching the other onboarding modules. The direct constructor is no longer accessible, and it also gained new parameters (uploadDocument, providerCode) in this release, so any previous positional call such as QES(true) would have silently changed meaning - the compile error steers you to the unambiguous QES.Builder instead.
Kotlin - before:
FlowConfig.Builder()
.addQES(QES(true))
Kotlin - after:
FlowConfig.Builder()
.addQES(
QES.Builder()
.setDownloadDocument(true)
.build()
)
Java - before:
new FlowConfig.Builder()
.addQES(new QES(true));
Java - after:
new FlowConfig.Builder()
.addQES(
new QES.Builder()
.setDownloadDocument(true)
.build()
);
11. Status enum gains UNSUPPORTED and COULD_NOT_COMPLETE values
Status gains two new constants, UNSUPPORTED and COULD_NOT_COMPLETE. DeviceStats.motionStatus never emits the new values, so existing runtime behavior for DeviceStats.motionStatus is unchanged.
It is source-breaking in Kotlin if you do an exhaustive when over Status without an else branch - such code will now fail to compile until it handles the new constants. A plain Java switch statement does not fail to compile when constants are added; it compiles and silently falls through to default (or does nothing if there is no default), so any Java switch over Status should add explicit handling for the new values to avoid silently mishandling them.
Kotlin - before:
val label = when (status) {
Status.PASS -> "pass"
Status.FAIL -> "fail"
Status.UNCLEAR -> "unclear"
}
Kotlin - after:
val label = when (status) {
Status.PASS -> "pass"
Status.FAIL -> "fail"
Status.UNCLEAR -> "unclear"
Status.UNSUPPORTED -> "unsupported"
Status.COULD_NOT_COMPLETE -> "could not complete"
}
Java - before:
String label;
switch (status) {
case PASS: label = "pass"; break;
case FAIL: label = "fail"; break;
case UNCLEAR: label = "unclear"; break;
default: label = "unknown";
}
Java - after:
String label;
switch (status) {
case PASS: label = "pass"; break;
case FAIL: label = "fail"; break;
case UNCLEAR: label = "unclear"; break;
case UNSUPPORTED: label = "unsupported"; break;
case COULD_NOT_COMPLETE: label = "could not complete"; break;
default: label = "unknown";
}
10. Minimum Compose Material3 and Compose versions raised to 1.4.0 / 1.8.0
The SDK's Compose-based (V2) screens are now built against Compose Material3 1.4.0 and Compose 1.8.0 (foundation / UI). This is not a change to any SDK API - your Kotlin/Java integration code is unaffected - but it raises the minimum versions of these libraries your app must resolve. Because Compose reaches your app transitively and Gradle resolves it with highest-version-wins, an app that resolves an older Compose Material3 / Compose set crashes at runtime (NoSuchMethodError / NoClassDefFoundError in androidx.compose.*) when opening a V2 screen such as the phone-number input, a dynamic-form dropdown or date field, or the CURP screen.
Most projects need no action: any app or dependency that pulls Compose Material3 1.4.0 (which itself depends on Compose 1.8.0+) already satisfies this. Act only if you have explicitly pinned these libraries below the required versions - remove the pin or raise it. The two floors are coupled, so aligning Material3 also pulls a compatible Compose set.
Migration to 5.50.0
Migration to 5.50.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. Replace setVideoLivenessRecordingEnabled() with setDeepsightConfiguration()
SelfieScan.Builder.setVideoLivenessRecordingEnabled() is deprecated in favor of setDeepsightConfiguration(), available on both SelfieScan.Builder and FaceAuthentication.Builder.
Note: Applies to both
SelfieScanandFaceAuthentication.
| Old | New equivalent |
|---|---|
setVideoLivenessRecordingEnabled(false) |
setDeepsightConfiguration(DeepsightConfiguration.Builder().setModality(DeepsightConfiguration.Modality.SINGLE_FRAME).build()) |
setVideoLivenessRecordingEnabled(true) |
setDeepsightConfiguration(DeepsightConfiguration.Builder().setModality(DeepsightConfiguration.Modality.VIDEO_LIVENESS).build()) |
The new API also exposes the MULTIMODAL modality (depth data collected, no video recording) and a setMotionEnabled() flag, which previously had no SDK equivalent.
Before (deprecated):
SelfieScan.Builder()
.setVideoLivenessRecordingEnabled(true)
.build()
After:
SelfieScan.Builder()
.setDeepsightConfiguration(
DeepsightConfiguration.Builder()
.setModality(DeepsightConfiguration.Modality.VIDEO_LIVENESS)
.build()
)
.build()
Java:
new SelfieScan.Builder()
.setDeepsightConfiguration(
new DeepsightConfiguration.Builder()
.setModality(DeepsightConfiguration.Modality.VIDEO_LIVENESS)
.build()
)
.build();
Migration to 5.49.0
Migration to 5.49.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. Renamed neutral and black color palette tokens
To align the V2 theme JSON with iOS so a single configuration file works across both platforms, the neutral and black keys in IncodeColorPalette have been renamed:
neutral->neutralLightblack->neutralDark
If you previously customized these colors via Kotlin:
IncodeWelcome
.getInstance()
.setCommonConfig(
CommonConfig.Builder()
.setThemeConfig(
IncodeThemeConfig(
colorPalette = IncodeColorPalette(
neutral = Color(0xFFFFFFFF),
black = Color(0xFF000000)
)
)
)
.build()
)
update the parameter names:
IncodeWelcome
.getInstance()
.setCommonConfig(
CommonConfig.Builder()
.setThemeConfig(
IncodeThemeConfig(
colorPalette = IncodeColorPalette(
neutralLight = Color(0xFFFFFFFF),
neutralDark = Color(0xFF000000)
)
)
)
.build()
)
If you provide the theme via a JSON config, rename the keys inside colorPalette:
Before
{
"colorPalette": {
"neutral": "#FFFFFF",
"black": "#000000"
}
}
After
{
"colorPalette": {
"neutralLight": "#FFFFFF",
"neutralDark": "#000000"
}
}
Theme JSON that still uses the old neutral / black keys will silently fall back to the defaults (#FFFFFF and #000000), because unknown keys are ignored during parsing. Update your JSON to use the new keys to keep your customizations applied.
2. SelfieScan.FaceAuthMode.SERVER deprecated - migrate to FaceAuthentication
SelfieScan.FaceAuthMode.SERVER is now deprecated. If your integration calls SelfieScan.Builder().setFaceAuthMode(SelfieScan.FaceAuthMode.SERVER), migrate to the FaceAuthentication module instead.
SelfieScan.FaceAuthMode.LOCAL (offline face login) and startFaceLogin() are not affected and remain fully supported.
3. Removed IncodeWelcome.getReport(...) and the ReportListener interface
The getReport(interviewId, ReportListener) method on IncodeWelcome, the ReportListener callback interface, and the ResponseEventReport class have been removed. The backing /omni/get/report backend endpoint is deprecated and reports can no longer be generated through the SDK. There is no in-SDK replacement.
If your integration previously invoked IncodeWelcome.getReport(...), remove those calls:
// No longer compiles - remove the call
incodeWelcome.getReport(interviewId, object : ReportListener {
override fun onReportFetched(uri: Uri?) { /* ... */ }
override fun onError(error: Throwable) { /* ... */ }
override fun onUserCancelled() { /* ... */ }
})
// No longer compiles - remove the call
incodeWelcome.getReport(interviewId, new ReportListener() {
@Override public void onReportFetched(Uri uri) { /* ... */ }
@Override public void onError(Throwable error) { /* ... */ }
@Override public void onUserCancelled() { /* ... */ }
});
4. DocumentScan.Builder chooser flags deprecated for V2 - migrate to setDocumentSources(...)
With the V2 Document Capture module enabled, DocumentScan.Builder.setShowTutorials(...) and DocumentScan.Builder.setShowDocumentProviderOptions(...) no longer affect the flow. The V2 module always opens on an intro screen and configures its source chooser exclusively via the new setDocumentSources(...) method. Both flags remain honored in V1.
If you previously used setShowDocumentProviderOptions(false) to send the user straight to the camera, configure a single-source set instead:
Kotlin - before:
DocumentScan.Builder()
.setDocumentType(DocumentType.ADDRESS_STATEMENT)
.setShowDocumentProviderOptions(false)
.setShowTutorials(false)
.build()
Kotlin - after:
DocumentScan.Builder()
.setDocumentType(DocumentType.ADDRESS_STATEMENT)
.setDocumentSources(setOf(DocumentScan.DocumentSource.CAMERA))
.build()
Java - before:
new DocumentScan.Builder()
.setDocumentType(DocumentType.ADDRESS_STATEMENT)
.setShowDocumentProviderOptions(false)
.setShowTutorials(false)
.build();
Java - after:
Set<DocumentScan.DocumentSource> sources = new HashSet<>();
sources.add(DocumentScan.DocumentSource.CAMERA);
new DocumentScan.Builder()
.setDocumentType(DocumentType.ADDRESS_STATEMENT)
.setDocumentSources(sources)
.build();
Pass any non-empty subset of CAMERA, FILE_UPLOAD, and IMAGE_UPLOAD to control which submission methods appear on the chooser. For document types that don't accept PDFs (e.g. DocumentType.MEDICAL_DOC), FILE_UPLOAD is dropped at runtime only when another source remains; configuring exactly setOf(DocumentScan.DocumentSource.FILE_UPLOAD) on such a type is rejected with a configuration error before the flow launches, so confirm a camera or image source remains for those document types.
Migration to 5.48.0
Migration to 5.48.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. Changed default values for face capture checks in SelfieScan and VideoSelfie modules
The defaults for setHeadCoverCheckEnabled(...) and setMaskCheckEnabled(...) on both SelfieScan.Builder and VideoSelfie.Builder have been changed from false to true. If you did not previously configure these flags, head cover and face mask validation will now be enforced by default during face capture.
To preserve the previous behavior, explicitly disable them on the builder(s) you use:
SelfieScan.Builder()
.setHeadCoverCheckEnabled(false)
.setMaskCheckEnabled(false)
.build()
VideoSelfie.Builder()
.setHeadCoverCheckEnabled(false)
.setMaskCheckEnabled(false)
.build()
new SelfieScan.Builder()
.setHeadCoverCheckEnabled(false)
.setMaskCheckEnabled(false)
.build();
new VideoSelfie.Builder()
.setHeadCoverCheckEnabled(false)
.setMaskCheckEnabled(false)
.build();
2. SQLCipher attribution required if you ship an open-source licenses screen
Local Room databases used by the SDK are now encrypted at rest with SQLCipher for Android, distributed under a BSD-style license. The license requires consumers that redistribute binaries (i.e. your application) to reproduce its copyright notice "in the documentation and/or other materials provided with the distribution".
If your application includes an "Open Source Licenses" screen, please add the SQLCipher notice listed in Licenses. No code change is needed if you do not ship such a screen.
Migration to 5.45.1
Migration to 5.45.1
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
Migration to 5.45.0
Migration to 5.45.0
If you are managing dependency versions manually (without the BOM), refer to the Module Versions section in the release notes for the updated version numbers.
1. Updates to document chooser behavior in IdScan module
The visibility of the document chooser screen is now controlled only by the "Show document chooser screen" flag on the Dashboard or setShowIdTypeChooser(...) in the SDK.
* When using startFlow / startWorkflow, the Dashboard setting is respected.
* When using startOnboarding / startOnboardingSection, the Dashboard setting is ignored and visibility is controlled exclusively via setShowIdTypeChooser(...).
Setting idType alone no longer hides the chooser and will be ignored.
If you previously pre-set idType (either using builder.setIdType(...) in the SDK or via the Dashboard) and expected the chooser to be hidden, you must now explicitly disable it or update the Flow configuration accordingly:
IdScan.Builder()
.setIdType(IdScan.IdType.ID)
.setShowIdTypeChooser(false)
.build()
new IdScan.Builder()
.setIdType(IdScan.IdType.ID)
.setShowIdTypeChooser(false)
.build();
2. Color palette changes
If you previously customized the application appearance by updating these colors from the color palette:
IncodeWelcome
.getInstance()
.setCommonConfig(
CommonConfig.Builder()
.setThemeConfig(
IncodeThemeConfig(
colorPalette = IncodeColorPalette(
negative500 = Color(0xffff5a5f),
negative600 = Color(0xffe71111),
positive500 = Color(0xff189f60),
positive600 = Color(0xff189f60)
)
)
)
.build()
)
or using a config JSON:
{
"colorPalette": {
"negative500": "#FF5A5F",
"negative600": "#E71111",
"positive500": "#189F60",
"positive600": "#189F60"
}
}
These keys have now been migrated to the following values:
negative500->negative400negative600->negative500positive500->positive400positive600->positive500
The mentioned colors are used for the following Color Modes:
Icon/Status/NegativeIcon/Status/PositiveSurface/Status/PositiveBorder/Status/Negative StaticBorder/Status/Positive Static
3. ID Capture V2 - Error Screen Customization
Wrong document side customization:
If you previously customized the Wrong document side error screen, add the following new string resources:
Add these strings:
<string name="onboard_sdk_id_capture_error_side_front">Capture the front side of the ID</string>
<string name="onboard_sdk_id_capture_error_side_back">Capture the back side of the ID</string>
Previous string:
<string name="onboard_sdk_id_capture_error_side">You’ve scanned the wrong document side. Please scan your document again.</string>
This string is no longer used.
No internet connection customization:
If you previously customized the No internet connection error screen, add the following new string resource:
Add this string:
<string name="onboard_sdk_no_internet_title">No internet connection</string>
Previous string:
<string name="onboard_sdk_id_capture_error_title">There was a problem</string>
The previously used string is still in use for other error screens and should be kept in your resources.
Retry button customization:
The retry button is now customized using a different string resource:
<string name="onboard_sdk_id_capture_retry">Refresh</string>
Previous string:
<string name="onboard_sdk_no_network_snackbar_action_text">Retry</string>
The previously used string is still in use for other error screens and should be kept in your resources.
4. Selfie V2 - Error Screen Customization
No internet connection customization:
If you previously customized the No internet connection error screen, add the following new string resource:
Add this string:
<string name="onboard_sdk_no_internet_title">No internet connection</string>
Previous string:
<string name="onboard_sdk_face_scan_failed_feedback_selfie_capture_failed_title">There was a problem</string>
The previously used string is still in use for other error screens and should be kept in your resources.
5. Changes in behavior for device environment detection
The behavior when detecting device environment vulnerabilities has changed:
- Hook or virtual environment detection: Detecting hook or virtual environment vulnerabilities in the SDK triggers a native crash, which cannot be caught or handled by application code, resulting in immediate app termination.
- Emulator and root detection: The flow is not aborted when emulator and root checks are detected. The onboarding process continues normally.
6. API Changes
6.1 The following IncodeWelcome.Builder methods have been removed
IncodeWelcome.Builder.disableVirtualEnvironmentDetection()
IncodeWelcome.Builder.disableRootDetection()
IncodeWelcome.Builder.disableEmulatorDetection()
IncodeWelcome.Builder.disableHookCheck()
IncodeWelcome.Builder.disableVirtualEnvironmentDetection()
IncodeWelcome.Builder.disableRootDetection()
IncodeWelcome.Builder.disableEmulatorDetection()
IncodeWelcome.Builder.disableHookCheck()
If you were using these methods in your code, remove them from your IncodeWelcome.Builder configuration as device environment checks can no longer be disabled.
6.2 The following exceptions have been removed
The following specific exceptions that extended DeviceEnvironmentException have been removed:
com.incode.welcome_sdk.commons.exceptions.IncodeException.EmulatorDetectedException
com.incode.welcome_sdk.commons.exceptions.IncodeException.RootDetectedException
com.incode.welcome_sdk.commons.exceptions.IncodeException.HookDetectedException
com.incode.welcome_sdk.commons.exceptions.IncodeException.VirtualEnvironmentDetectedException
If you were checking for these Exceptions in your code, remove any specific handling of them as your app will no longer get this direct feedback.
7. Expected crashes when running in a virtual environment
It is expected that the app crashes with the following stacktraces when a virtual environment is used. For example:
java.lang.NullPointerException
at com.incode.welcome_sdk.ThemeConfiguration$Builder.setLabelSmallStyle(SourceFile:1066)
at com.incode.welcome_sdk.f.c(SourceFile:150)
at com.incode.welcome_sdk.data.local.m.as(SourceFile:22)
at com.incode.welcome_sdk.IncodeWelcome.startOnboardingSection(SourceFile:18)
java.lang.NullPointerException: Attempt to get length of null array
at com.incode.welcome_sdk.data.IncodeWelcomeRepository.d(SourceFile:320)
at com.incode.welcome_sdk.data.IncodeWelcomeRepository.i(SourceFile:214)
8. Selfie V2 - No Internet Error Screen Retry Button Change
Retry button customization:
The retry button label shown on the Selfie Scan no internet error screen now uses a dedicated string resource:
<string name="onboard_sdk_face_scan_retry">Refresh</string>
Previous string:
<string name="onboard_sdk_try_again">Try again</string>
If you override onboard_sdk_try_again to customize the retry button on the no internet screen, you must now override onboard_sdk_face_scan_retry instead.
The onboard_sdk_try_again string is still used for other retry scenarios.
9. Selfie V2 - Capture-Only Mode Success Screen Text Change
Success label customization:
In capture-only mode, the Selfie Scan success screen now uses a different string resource:
<string name="onboard_sdk_face_captured">Face captured!</string>
Previous string:
<string name="onboard_sdk_enroll_success">Success!</string>
The previously used string is still in use for non-capture-only mode and should be kept in your resources.
10. ID Capture and Selfie V2 - Permission Open Settings Screen Text Change
Open settings button customization:
The Open settings label shown on the Permission open settings screen now uses a dedicated string resource:
<string name="onboard_sdk_permission_allow_permission_action">Allow permission</string>
Previous string:
<string name="onboard_sdk_permission_open_setting_action">Open settings</string>
The previously used string is still in use for the Geolocation module and should be kept in your resources.
Migration to 5.44.0
Migration to 5.44.0
1. Upgrade dependencies
Consider migrating to the Incode BOM
To help facilitate easier version upgrades, 5.44.0 introduces the Incode Bill of Materials (BOM). This can be used to upgrade all relevant Incode library dependencies from one place instead of multiple steps to upgrade library dependency versions. To get started,
Replace:
implementation 'com.incode.sdk:welcome:5.43.0'
implementation 'com.incode.sdk:core-light:3.0.7'
implementation("com.incode.sdk:welcome:5.43.0")
implementation("com.incode.sdk:core-light:3.0.7")
With:
implementation platform('com.incode.sdk:bom:5.44.0')
implementation 'com.incode.sdk:welcome'
implementation 'com.incode.sdk:core-light'
// Plus any other Incode SDK dependencies... (without the version numbers)
implementation(platform("com.incode.sdk:bom:5.44.0"))
implementation("com.incode.sdk:welcome")
implementation("com.incode.sdk:core-light")
// Plus any other Incode SDK dependencies... (without the version numbers)
See the Incode Bill of Materials (BOM) section of the Setup Guide for more info.
or, Upgrade dependencies manually
If you prefer to continue updating all dependencies manually, be sure to update welcome as usual:
implementation 'com.incode.sdk:welcome:5.44.0'
implementation("com.incode.sdk:welcome:5.44.0")
and update the core-light dependency to the latest version:
implementation 'com.incode.sdk:core-light:3.0.8'
implementation("com.incode.sdk:core-light:3.0.8")
2. Upload Digital ID V2
Upload error screen customization:
If you previously customized the upload error screen, add the following new string resource:
Add this string:
<string name="onboard_sdk_validation_error_button_text">Scan your ID</string>
Previous string:
<string name="onboard_sdk_id_capture_tutorial_title">Scan your ID</string>
This string is now used only for customizing the ID Capture V2 tutorial screen title.
3. DocumentType has moved
The DocumentType class has been moved from the com.incode.welcome_sdk.ui.camera.id_validation.base package
to com.incode.welcome_sdk.data.
Replace the following import statement
com.incode.welcome_sdk.ui.camera.id_validation.base.DocumentType
with
com.incode.welcome_sdk.data.DocumentType
4. Package name change: selfie_scan renamed to selfie_capture
The package name selfie_scan has been renamed to selfie_capture.
Update all imports from com.incode.welcome_sdk.ui.selfie_scan.* to com.incode.welcome_sdk.ui.selfie_capture.* throughout your codebase.
This change was required due to DexGuard constraints around package naming and obfuscation.
5. Transition/Loading screen removed
The transition/loading screen that was shown between modules has been completely removed. If your integration had any customization for this screen (e.g., overriding onboard_sdk_activity_transition.xml, setting IncodeTransitionScreenState.isEnabled, or customizing transition string resources), those customizations can be safely deleted.
6. Migrate any custom ThemeConfiguration to the V2 equivalent
If your previous integration had any UI customization in supported modules through Theme Configuration, these customizations will now need to be migrated to the equivalents in UXv2. See the Migrating Theme Configurations to UXv2 Guide for more details.
7. Changed default values in FaceMatch module config (optional)
With the move to UxV2, the showUserExists config is now false by default.
To preserve the old behavior, you can use:
FaceMatch.Builder()
.setShowUserExists(true)
.build()
new FaceMatch.Builder()
.setShowUserExists(true)
.build();
Migration to 5.43.0
Migration to 5.43.0
1. Update core-light dependency to the latest version
implementation 'com.incode.sdk:core-light:3.0.7'
implementation("com.incode.sdk:core-light:3.0.7")
2. If you use any of the following optional dependencies, make sure to update to the latest versions
implementation 'com.incode.sdk:nfc:1.5.2'
implementation("com.incode.sdk:nfc:1.5.2")
3. Update string resources for the "Need Help" screen in the IdScan v2 module
The "Need Help" screen has been redesigned, and the customizable strings have been replaced. If you override any of the following strings in your app, replace them with the new ones listed below.
No action is required if you do not override these strings.
Replaced string resources
Replace overrides of:
<string name="onboard_sdk_id_capture_help_title">Need help?</string>
<string name="onboard_sdk_id_capture_help_subtitle">Some considerations</string>
<string name="onboard_sdk_id_capture_help_manual_photo_button_text">Take the photo manually</string>
<string name="onboard_sdk_id_capture_help_align_title">Center your document in the frame</string>
<string name="onboard_sdk_id_capture_help_align_subtitle">The photo will be taken automatically</string>
<string name="onboard_sdk_id_capture_help_blur_title">Avoid blurriness on the document</string>
<string name="onboard_sdk_id_capture_help_blur_subtitle">Zoom in and out, or tap on the document</string>
<string name="onboard_sdk_id_capture_help_glare_title">Avoid glare on the document</string>
<string name="onboard_sdk_id_capture_help_glare_subtitle">Find a better lighting to avoid reflections</string>
<string name="onboard_sdk_id_capture_help_darkness_title">Avoid darkness on the document</string>
<string name="onboard_sdk_id_capture_help_darkness_subtitle">Find a place with better lighting</string>
with:
<string name="onboard_sdk_id_capture_common_issues_title">Common issues</string>
<string name="onboard_sdk_id_capture_common_issues_glare_title">Glare present</string>
<string name="onboard_sdk_id_capture_common_issues_glare_subtitle">Tilt the ID slightly up or down to minimize the reflection</string>
<string name="onboard_sdk_id_capture_common_issues_blur_title">Blur present</string>
<string name="onboard_sdk_id_capture_common_issues_blur_subtitle">Move ID further away or closer to your phone until the image is focused</string>
<string name="onboard_sdk_id_capture_common_issues_info_not_readable_title">Info is not readable</string>
<string name="onboard_sdk_id_capture_common_issues_info_not_readable_subtitle">Minimize camera shake by holding your phone steady</string>
<string name="onboard_sdk_id_capture_common_issues_try_again_button">@string/onboard_sdk_try_again</string>
4. API Changes
FaceAuthenticationResult.error type changed from FaceAuthenticationException? to Throwable? to support non-domain failures.
Consumers should no longer assume the error is a FaceAuthenticationException.
Migration to 5.42.0
Migration to 5.42.0
1. Upgrade compileSdk
With the update of the internal CameraX dependencies, you will need to upgrade your project's compileSdk to level 35:
compileSdk 35
2. Update Android Gradle Plugin (AGP)
Bumping compileSdk to 35 requires Android Gradle Plugin (AGP) 8.6.0 or higher.
Update your project-level build.gradle or settings.gradle file to use the new plugin version.
classpath "com.android.tools.build:gradle:8.6.0"
3. Update Gradle Wrapper
AGP 8.6.0 requires Gradle 8.7 or higher.
Update your Gradle wrapper configuration in gradle/wrapper/gradle-wrapper.properties:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
4. Update core-light dependency to the latest version
implementation 'com.incode.sdk:core-light:3.0.6'
5. If you use any of the following optional dependencies, make sure to update to the latest versions
implementation 'com.incode.sdk:nfc:1.5.1'
6. API changes
6.1 DeviceEnvironmentException is moved and extended
The DeviceEnvironmentException class has been moved from the com.incode.welcome_sdk.commons.exceptions package
to com.incode.welcome_sdk.commons.exceptions.IncodeException.
Replace the following import statement
com.incode.welcome_sdk.commons.exceptions.DeviceEnvironmentException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.DeviceEnvironmentException
If you were catching DeviceEnvironmentExceptions, you can now also catch more specific exceptions that extend it:
EmulatorDetectedExceptionRootDetectedExceptionHookDetectedExceptionVirtualEnvironmentDetectedException
6.2 PermissionsDeniedException has been replaced
Replace instances of
com.incode.welcome_sdk.commons.exceptions.video_selfie.PermissionsDeniedException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.PermissionNotGranted
6.3 PermissionDeniedException has been replaced
Replace instances of
com.incode.welcome_sdk.commons.exceptions.PermissionDeniedException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.PermissionNotGranted
6.4 CameraPermissionDeniedException has been replaced
Replace instances of
com.incode.welcome_sdk.commons.exceptions.video_selfie.CameraPermissionDeniedException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.PermissionNotGranted.CameraPermissionNotGranted
6.5 MicrophonePermissionDeniedException has been replaced
Replace instances of
com.incode.welcome_sdk.commons.exceptions.video_selfie.MicrophonePermissionDeniedException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.PermissionNotGranted.RecordAudioPermissionNotGranted
6.6 ScreenRecordingPermissionDeniedException has been replaced
Replace instances of
com.incode.welcome_sdk.commons.exceptions.video_selfie.ScreenRecordingPermissionDeniedException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.PermissionNotGranted.ScreenCapturePermissionNotGranted
6.7 UnknownException has been renamed
Replace instances of
com.incode.welcome_sdk.commons.exceptions.IncodeException.UnknownException
with
com.incode.welcome_sdk.commons.exceptions.IncodeException.GenericException
6.8 The following unused exceptions have been removed
com.incode.welcome_sdk.commons.exceptions.ApprovalForbiddenException
com.incode.welcome_sdk.commons.exceptions.ExistingSessionException
Migration to 5.41.0
Migration to 5.41.0
1. Update core-light dependency to the latest version
implementation 'com.incode.sdk:core-light:3.0.5'
2. If you use any of the following optional dependencies, make sure to update to the latest versions
implementation 'com.incode.sdk:nfc:1.5.0'
3. API changes
3.1 Breaking change in SelfieScanListener
The SelfieScanListener interface has been updated to include a new method: onSelfieScanReady(NonUiSelfieScanController).
This change requires all implementations of the SelfieScanListener interface to provide an implementation for this new method.
If you don't use non-ui mode, you can leave the method empty.
An example of build error: does not override abstract method onSelfieScanReady(NonUiSelfieScanController) in SelfieScanListener