Android

The following guide will get you started with the Android SDK for Incode Onboarding.

Minimum hardware requirements

Ram: 3GB
Back-facing camera: 5MP
Front-facing (selfie) camera: 2MP

Installation

The Incode Android SDK is distributed through Maven. To receive credentials for the SDK, please reach out to your enterprise customer success manager or contact [email protected].

Add the following maven repository to your project dependencies. Read the Gradle documentation about declaring dependencies for more information.

repositories {
    maven {
        url "https://repo.incode.com/artifactory/libs-incode-welcome"
        credentials {
            username = "organizationUsername"
            password = "xxxxxxxxxxxxxxxxxxxx"
        }
    }
}

The Incode SDK is dependent on jitpack, so the following maven repository needs to be added as well.

repositories {
    maven { url "https://jitpack.io" }
}

Finally, don't forget to add Google and Maven Central to the file if it's not there already.

repositories {
    google()
    mavenCentral()
}

The dependencies should look like the following.

repositories {
    google()
    mavenCentral()

    maven { url "https://jitpack.io" }
    maven {
        url "https://repo.incode.com/artifactory/libs-incode-welcome"
        credentials {
            username = "organizationUser"
            password = "password"
        }
    }
}

In your module-level app/build.gradle, we require a minimum of Java 8 for both source and targetCompatibility. To enforce this, add the following code inside your android{} block:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

Next, in your app/build.gradle, add Incode library dependencies as described below.

Dependencies

Core dependencies must be included. Optional ones should be added as needed, based on the use case - see below.

dependencies {
    ...

    // Incode Welcome SDK
    implementation 'com.incode.sdk:welcome:5.31.0' // Incode Welcome SDK
    implementation 'com.incode.sdk:core-light:2.6.5' // Required core dependency
    implementation 'com.incode.sdk:camera:1.0.1' // Required core dependency if ID capture V2 experience should be used

    // The following dependencies are optional and needed only in very specific use cases.
    // Make sure you are using the features they provide before adding the dependencies below.
    implementation 'com.incode.sdk:extensions:1.1.0' // Optional dependency
    implementation 'com.incode.sdk:kiosk-login:1.3.5' // Optional dependency
    implementation 'com.incode.sdk:nfc:1.3.5' // Optional dependency
    implementation 'com.incode.sdk:qr-face-login:1.2.3' // Optional dependency
    implementation 'com.incode.sdk:video-streaming:1.5.5' // Optional dependency

    implementation 'com.incode.sdk:model-face-recognition:3.2.0' // Optional dependency
    implementation 'com.incode.sdk:model-id-face-detection:2.1.0' // Optional dependency
    implementation 'com.incode.sdk:model-liveness-detection:3.2.0' // Optional dependency
}
  • The core-light dependency is required as it contains the image processing libraries used in the Welcome SDK.

  • The extensions dependency is optional and is necessary only for using Dynamic Localization or a custom Theme Configuration.

  • The kiosk-login dependency is optional and is needed if you are using the Kiosk Login feature of the SDK. It also requires additional configuration, as described here.

  • The nfc dependency is optional and is required if you are using the NFC Scanning feature of the SDK. Additional configuration is also required, as described here.

  • The qr-face-login dependency is optional and is necessary if you are using the QR Face Login feature of the SDK. It also requires additional repositories configuration, as described here.

  • The video-streaming dependency is optional and is needed if you are using the Conference module or the streamFrames feature in the IdScan and SelfieScan modules.

  • The model-face-recognition dependency is optional and is required if you are using the face recognition feature that runs locally on the device. This feature is only available for Face Login.

  • The model-id-face-detection dependency is optional and is necessary if you are using checks to detect the front/back side of an ID.

  • The model-liveness-detection dependency is optional and is required if you are using the liveness detection feature that runs locally on the device.

Finally, try building the project after all of the dependencies are added. If you encounter issues during the build process, refer to the troubleshooting section.

Once the project successfully builds. It is time to start integration.

Troubleshooting

Attribute application@allowBackup value=(true) from AndroidManifest.xml

Attribute application@allowBackup value=(true) from AndroidManifest.xml is also present at [com.incode.sdk:welcome:x.x.x] AndroidManifest.xml value=(false).
Suggestion: add 'tools:replace="android:allowBackup"' to `<application>` element at AndroidManifest.xml to override.

Solution

This means that you have set allowBackup in your AndroidManifest.xml to true, but the Welcome SDK has this value set to false.
Having allowBackup set to true is a potential security issue, so we suggest setting it to false.
If you are sure that you wish to allow backups, then add tools:replace="android:allowBackup" to <application> element in your AndroidManifest.xml.
If you already have some attributes in tools:replace, separate them with commas (for example: "android:label,android:allowBackup").

Static interface methods are only supported starting with Android N

Static interface methods are only supported starting with Android N (--min-api 24): Lbutterknife/Unbinder;lambda$static$0()V
Error while dexing. The dependency contains Java 8 bytecode. Please enable desugaring by adding the following to build.gradle
android {
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
}}

Solution

In your module-level [module]/build.gradle, add the following code to android{} closure:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

All modules with native libraries must support the same set of ABIs

Execution failed for task ':app:packageDebugBundle'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > All modules with native libraries must support the same set of ABIs, but module 'base' supports '[X86, ARMEABI_V7A, ARM64_V8A, X86_64, MIPS, ARMEABI]' and module 'incode_core' supports '[ARMEABI_V7A, X86, X86_64, ARM64_V8A]'.
- problem when generating bundles.

Solution

Add the following ndk abi filters to your module-level app/build.gradle inside defaultConfig{} closure:

ndk {
    abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
}

FATAL EXCEPTION: RxCachedThreadScheduler

E/AndroidRuntime: FATAL EXCEPTION: RxCachedThreadScheduler-2
    Process: com.incode.welcome.example, PID: 6842
    io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.NoSuchMethodError: No virtual method log(ILjava/lang/String;Ljava/lang/Throwable;)V in class Lokhttp3/internal/platform/Platform; or its super classes (declaration of 'okhttp3.internal.platform.Platform' appears in /data/app/com.incode.welcome.example-HnCVs4pdPTZBq3BhFsJmdQ==/base.apk!classes3.dex)
        at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:69)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
    Caused by: java.lang.NoSuchMethodError: No virtual method log(ILjava/lang/String;Ljava/lang/Throwable;)V in class Lokhttp3/internal/platform/Platform; or its super classes (declaration of 'okhttp3.internal.platform.Platform' appears in /data/app/com.incode.welcome.example-HnCVs4pdPTZBq3BhFsJmdQ==/base.apk!classes3.dex)
        at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:114)
        at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:173)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
        at okhttp3.internal.connection.RealCall.execute(RealCall.kt:148)
        at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
        at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:45)
        at io.reactivex.Observable.subscribe(Observable.java:12267)
        at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
        at io.reactivex.Observable.subscribe(Observable.java:12267)
        at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:32)
        at io.reactivex.Observable.subscribe(Observable.java:12267)
        at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
        at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

Solution

This crash occurs when the okhttp3:okhttp dependency version is different from okhttp3:logging-interceptor or okhttp3:okhttp-urlconnection dependencies and trying to init Incode SDKs.

For example, in case you have in the Project's External Libraries the following dependencies, you will face the crash because of the version inconsistency:

  • okhttp3:logging-interceptor:3.4.1
  • okhttp3:okhttp-urlconnection:3.4.1
  • okhttp3:okhttp:4.5.0

To fix the crash, for the example above, you need to bump the version of okhttp3:logging-interceptor & okhttp3:okhttp-urlconnection to 4.5.0.

Add the following implementations inside build.gradle to override existing lower versions:

dependencies {
    ...

    implementation 'com.squareup.okhttp3:logging-interceptor:4.5.0'
    implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.5.0'
}

It is important to note that the crash will still occur in the case you only have the logging-interceptor or okhttp-urlconnection dependency.

Crashes if you have in External Libraries these dependencies:

  • okhttp3:logging-interceptor:3.4.1
  • okhttp3:okhttp:4.5.0

Crashes as well if you have in External Libraries these dependencies:

  • okhttp3:okhttp-urlconnection:3.4.1
  • okhttp3:okhttp:4.5.0

InvalidUserCodeException: Build was configured to prefer settings

org.gradle.api.InvalidUserCodeException: Build was configured to prefer settings repositories over project repositories but repository 'maven' was added by build file 'build.gradle'

Solution

For projects using Gradle 6.8 or higher, a new way of defining dependencies in settings.gradle with the dependencyResolutionManagement block was introduced. Moving the maven repo declaration from the project build.gradle to here should resolve it. See also StackOverflow.

dependencyResolutionManagement {
    ...
    repositories {
        ...
        maven {
            url "https://repo.incode.com/artifactory/libs-incode-welcome"
            credentials {
                username = "organizationUsername"
                password = "xxxxxxxxxxxxxxxxxxxx"
            }
        }
    }
}

A problem occurred evaluating root project

Build was configured to prefer settings repositories over project repositories but repository 'Google' was added by build file 'build.gradle'

Solution

In the settings.gradle file, ensure that the repositoriesMode is set to RepositoriesMode.PREFER_PROJECT

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
    repositories {
        google()
        mavenCentral()
    }
}

Fatal error during SentryAndroid.init(...)

Since version 5.24.0, the Incode SDK includes the Sentry SDK for crash reporting.
We are currently using version 7.x.x, and if your project happens to be using a different major version (such as 6.x.x),
the following crash can occur:

java.lang.RuntimeException: Unable to get provider io.sentry.android.core.SentryInitProvider: java.lang.RuntimeException: Failed to initialize Sentry's SDK
...
Caused by: java.lang.RuntimeException: Failed to initialize Sentry's SDK
...
Caused by: java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.NoSuchMethodError: No virtual method setEnableScopeSync(Z)V...

If you are affected by this error, you will need to upgrade to version 5.25.0 or newer, and apply the following workaround:

  1. Exclude the Sentry library from Incode SDK:
implementation ('com.incode.sdk:welcome:5.25.0') { // Mandatory dependency
    exclude group: 'io.sentry', module: 'sentry'
}
  1. Disable Incode SDK's crash reporting:
new IncodeWelcome.Builder()
    ...
    .setCrashReportingEnabled(false)
    .build();
IncodeWelcome.Builder()
    ...
    .setCrashReportingEnabled(false)
    .build()

What’s Next

Next, check out the Standard Integration guide on getting Incode up and running.