# Installation

This page covers everything you need to add the Incode Android SDK to your project. It covers build requirements, repository and dependency setup with Gradle, the Incode Bill of Materials (BOM), required and optional permissions, initializing the SDK, and enabling test mode. After the project builds, [choose an integration approach](https://developer.incode.com/docs/android-common-implementation-patterns).

***

## Build Requirements

Ensure your build environment meets the following minimum requirements:

- **Java**: Java 8 in your module-level `[module]/build.gradle`, applied to both `sourceCompatibility` and `targetCompatibility`. This page explains where to set this.
- **compileSdk**: 35 or higher. The SDK's bundled AndroidX dependencies require apps to compile against API 35 or later. If your `compileSdk` is lower, the build fails the AAR-metadata check with `... require ... compile against version 35 or later`. Set `compileSdk 35` or higher in your module-level `build.gradle`. This is independent of `minSdk` and `targetSdk`.
- **minSdk**: 23; raise to 24 if you use `video-streaming`. Raise to 28 if you use Google Wallet.
- **targetSdk**: Your choice; the SDK itself targets API 33.
- **Build tooling**: Android Gradle Plugin 8.6.0, Gradle 8.7, Kotlin 1.9.25. Newer compatible versions also work. Matching your Android Studio's bundled AGP avoids IDE sync slowdowns.

Also, ensure your devices meet the [device requirements](https://developer.incode.com/docs/android-sdk#device-requirements). Then complete the following steps in order.

***

## Add Repositories

The Incode Android SDK is distributed through GitHub Packages. To receive credentials, contact your enterprise customer success manager or [help@incode.com](mailto:help@incode.com).

<Callout icon="⚠️" theme="warn">
  ### Artifactory Distribution Has Ended

  Support for Artifactory distribution ended September 19, 2025. If you are using Artifactory in your production integration, migrate to GitHub Packages to maintain uninterrupted access to the SDK.
</Callout>

The code blocks below use the project-level `build.gradle`. On projects that use Gradle's centralized repository management, which is the default for newer Android Studio projects, add the same `repositories { }` entries to the `dependencyResolutionManagement` block in `settings.gradle` instead. The URLs and credentials are identical. If you keep them in the project `build.gradle`, make sure `settings.gradle` is not set to `RepositoriesMode.FAIL_ON_PROJECT_REPOS`.

### Add the GitHub Packages Repository

Add the following to your project-level `build.gradle`. For more information about declaring repositories, see the [Gradle documentation](https://docs.gradle.org/current/userguide/declaring_repositories.html).

```groovy build.gradle (Project)
repositories {
    maven {
        url "https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages"
        credentials {
            username = "incode-customers"
            password = "YOUR_GITHUB_TOKEN"
        }
    }
}
```
```kotlin build.gradle.kts (Project)
repositories {
    maven {
        url = uri("https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages")
        credentials {
            username = "incode-customers"
            password = "YOUR_GITHUB_TOKEN"
        }
    }
}
```

Keep `username` as `incode-customers`. Replace `YOUR_GITHUB_TOKEN` with the access token Incode provides. The token must have the `read:packages` scope and access to the `android-omni-packages` registry, or dependency resolution fails with `401 Unauthorized`. Do not commit the token. Store it outside source control—for example, in `~/.gradle/gradle.properties` or an environment variable—and read it in:

```groovy build.gradle (Project)
credentials {
    username = "incode-customers"
    password = providers.gradleProperty("incode.githubToken").get()
}
```

### Add the JitPack Repository

The SDK depends on JitPack. Add the following Maven repository.

```groovy build.gradle (Project)
repositories {
    maven { url "https://jitpack.io" }
}
```
```kotlin build.gradle.kts (Project)
repositories {
    maven("https://jitpack.io")
}
```

### Add Google and Maven Central

If the Google and Maven Central repositories are not already in your project-level `build.gradle` file, add them.

```groovy build.gradle (Project)
repositories {
    google()
    mavenCentral()
}
```
```kotlin build.gradle.kts (Project)
repositories {
    google()
    mavenCentral()
}
```

Combined, your project-level repositories should look like this:

```groovy build.gradle (Project)
repositories {
    google()
    mavenCentral()

    maven { url "https://jitpack.io" }
    maven {
        url "https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages"
        credentials {
            username = "incode-customers"
            password = "YOUR_GITHUB_TOKEN"
        }
    }
}
```
```kotlin build.gradle.kts (Project)
repositories {
    google()
    mavenCentral()

    maven("https://jitpack.io")
    maven {
        url = uri("https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages")
        credentials {
            username = "incode-customers"
            password = "YOUR_GITHUB_TOKEN"
        }
    }
}
```

***

## Enforce Java 8

Add the following code inside your `android{}` block in your `[module]/build.gradle`. `[module]` refers to your app or library module, not an [Incode SDK module](https://developer.incode.com/docs/android-individual-modules).

```groovy build.gradle (Module)
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
```
```kotlin build.gradle.kts (Module)
compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}
```

***

## Add the Incode Bill of Materials (BOM)

The Incode BOM streamlines dependency version control. When you specify the BOM's version, it automatically ensures all Incode dependencies in your project use compatible versions. You don't need to assign versions to each dependency individually. Update the BOM version to update all dependencies at once. See [BOM Version Mapping](https://developer.incode.com/docs/bom-version-mapping) for the latest version.

Specifying the BOM only downloads a POM file with a version mapping. You must still [declare each dependency](#declare-dependencies) individually in your `[module]/build.gradle`.

Add the BOM to the `dependencies` block in your `[module]/build.gradle`.

```groovy build.gradle (Module)
dependencies {
    ...

    implementation platform('com.incode.sdk:bom:5.49.0')
}
```
```kotlin build.gradle.kts (Module)
dependencies {
    ...

    implementation(platform("com.incode.sdk:bom:5.49.0"))
}
```

***

## Declare Dependencies

Add the following to your `[module]/build.gradle`. `welcome` and `core-light` are required. All others are optional; add them only if your integration uses the features they provide. If you [added the Incode BOM](#add-the-incode-bill-of-materials-bom), omit version numbers.

```groovy build.gradle (Module)
dependencies {
    ...

    // Incode Omni SDK
    implementation 'com.incode.sdk:welcome' // Required core dependency
    implementation 'com.incode.sdk:core-light' // Required core dependency

    // 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' // Optional dependency
    implementation 'com.incode.sdk:nfc' // Optional dependency
    implementation 'com.incode.sdk:video-streaming' // Optional dependency

    implementation 'com.incode.sdk:model-face-recognition' // Optional dependency
    implementation 'com.incode.sdk:model-liveness-detection' // Optional dependency
    implementation 'com.incode.sdk:model-face-occlusion' // Optional dependency
    implementation 'com.incode.sdk:model-age-estimation' // Optional dependency
    implementation("com.incode.sdk:wallets") // Optional dependency
}
```
```kotlin build.gradle.kts (Module)
dependencies {
    ...

    // Incode Omni SDK
    implementation("com.incode.sdk:welcome") // Required core dependency
    implementation("com.incode.sdk:core-light") // Required core dependency

    // 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") // Optional dependency
    implementation("com.incode.sdk:nfc") // Optional dependency
    implementation("com.incode.sdk:video-streaming") // Optional dependency

    implementation("com.incode.sdk:model-face-recognition") // Optional dependency
    implementation("com.incode.sdk:model-id-face-detection") // Optional dependency
    implementation("com.incode.sdk:model-liveness-detection") // Optional dependency
    implementation("com.incode.sdk:model-face-occlusion") // Optional dependency
    implementation("com.incode.sdk:model-age-estimation") // Optional dependency
    implementation("com.incode.sdk:wallets") // Optional dependency
}
```

| Dependency                 | Type     | Description                                                                                                                                                                                                                                                                                                                             |
| :------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `welcome`                  | Required | Core dependency; contains all core SDK functionality and the `IncodeWelcome` entry point.                                                                                                                                                                                                                                               |
| `core-light`               | Required | Contains image-processing libraries used throughout the SDK.                                                                                                                                                                                                                                                                            |
| `extensions`               | Optional | Required for custom theme configuration, dynamic localization, and runtime localization. See [Customization](https://developer.incode.com/docs/android-customization).                                                                                                                                                    |
| `nfc`                      | Optional | Required for the NFC Scan module. See [NFC Scan](https://developer.incode.com/docs/android-nfc-scan-2) for additional configuration.                                                                                                                                                                                      |
| `video-streaming`          | Optional | Required by the [Conference module](https://developer.incode.com/docs/android-conference-assisted-video) and the `streamFrames` feature in the [ID Scan](https://developer.incode.com/docs/android-id-scan) and [Selfie Scan](https://developer.incode.com/docs/android-selfie-scan) modules. |
| `model-face-recognition`   | Optional | Required for on-device face recognition. Used by face login in the [Selfie Scan module](https://developer.incode.com/docs/android-selfie-scan)​ only.                                                                                                                                                                     |
| `model-liveness-detection` | Optional | Required for on-device liveness detection in the [Selfie Scan module](https://developer.incode.com/docs/android-selfie-scan) via `SelfieScan.Builder().setFaceAuthMode(SelfieScan.FaceAuthMode.LOCAL)`.                                                                                                                   |
| `model-face-occlusion`     | Optional | Required for on-device face occlusion detection in the [Selfie Scan module](https://developer.incode.com/docs/android-selfie-scan) via `SelfieScan.Builder().setFaceOcclusionEnabled(true)`.                                                                                                                              |
| `model-age-estimation`     | Optional | Required for on-device age estimation in the [Selfie Scan module](https://developer.incode.com/docs/android-selfie-scan) via `SelfieScan.Builder().setOnDeviceFaceResultsSubmissionEnabled(true)`.                                                                                                                        |
| `wallets`                  | Optional | Required for wallet integrations, including Google Wallet ID.                                                                                                                                                                                                                                                                           |

After adding dependencies, build the project. [Troubleshoot](https://developer.incode.com/docs/android-troubleshooting) if you encounter errors. For the version mapped to each dependency, see [BOM Version Mapping](https://developer.incode.com/docs/bom-version-mapping).

### Override a Dependency Version

Overriding a BOM dependency version is not recommended. If necessary, specify the version where it would normally be omitted.

```groovy build.gradle (Module)
dependencies {
    ...

    implementation platform('com.incode.sdk:bom:5.49.0')

    // Required core dependencies
    implementation 'com.incode.sdk:welcome'
    implementation 'com.incode.sdk:core-light'

    // Optional dependencies
    implementation('com.incode.sdk:video-streaming') {
        version {
            strictly 'x.x.x-1'
        }
    }
}
```
```kotlin build.gradle.kts (Module)
dependencies {
    ...

    implementation(platform("com.incode.sdk:bom:5.49.0"))

    // Required core dependencies
    implementation("com.incode.sdk:welcome")
    implementation("com.incode.sdk:core-light")

    // Optional dependencies
    implementation("com.incode.sdk:video-streaming") {
        version {
            strictly("x.x.x-1")
        }
    }
}
```

***

## Declare Required Permissions

The SDK declares the following permissions in its manifest files:

- `com.incode.sdk:welcome`
  ```xml
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.VIBRATE" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  ```
- `com.incode.sdk:nfc`
  ```xml
  <uses-permission android:name="android.permission.NFC" />
  ```

If your app does not use the screen recording features of the ID Scan, Selfie Scan, or Video Selfie modules, you can omit the foreground service permissions. Add the following to your `AndroidManifest.xml`:

```xml AndroidManifest.xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" tools:node="remove" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" tools:node="remove" />
```

If the manifest fails to merge during a build, [troubleshoot](https://developer.incode.com/docs/android-troubleshooting).

<Callout icon="📘" theme="info">
  ### Camera Lint Warning

  The SDK manifest declares `<uses-feature android:name="android.hardware.camera" />`, so the merged manifest already advertises the camera requirement. If Android Lint flags `PermissionImpliesUnsupportedHardware` on your own module, declare the feature explicitly in your `AndroidManifest.xml`:&#x20;

  `<uses-feature android:name="android.hardware.camera" android:required="false" />`

  Use `android:required="false"` only if you want your app installable on devices without a camera. The SDK's capture flows require one.
</Callout>

***

## Add Optional Permissions

Some SDK features work better with additional permissions. These permissions may subject your app to additional scrutiny when publishing on Google Play. Declare them only if your app has an existing use case for them.

### Query All Apps on Android 11+

On Android 11 and later, root detection skips additional actions. This can result in some rooted devices going undetected. Add the following permission to enable the SDK's root detection to take more actions and find evidence of a rooted device.

```xml
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
```

On earlier Android versions, actions that require `QUERY_ALL_PACKAGES` are taken by default.

### Enable Higher Sampling Rates on Android 12+

On Android 12 and later, the second highest sample rate is used by default when determining the device's `motionStatus` for the ID Scan and Selfie Scan modules. Add the following permission to maximize the sampling rate used.

```xml
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
```

On earlier Android versions, the highest sampling rate is used automatically.

***

## Initialize the SDK

Add the following to the class that extends `Application`:

```kotlin
override fun onCreate() {
    super.onCreate()
    ...
    IncodeWelcome.Builder(this, WELCOME_API_URL, WELCOME_API_KEY)
        .setSSLConfig(sslConfig) // optional SSL config for on-premise servers
        .setLoggingEnabled(loggingEnabled) // enable/disable logcat logs. These are enabled by default
        .build()
    ...
}
```
```java
@Override
public void onCreate() {
    super.onCreate();
    ...
    new IncodeWelcome.Builder(this, WELCOME_API_URL, WELCOME_API_KEY)
            .setSSLConfig(sslConfig) // optional SSL config for on-premise servers
            .setLoggingEnabled(loggingEnabled) // enable/disable logcat logs. These are enabled by default
            .build();
    ...
}
```

- `WELCOME_API_URL` and `WELCOME_API_KEY` are provided by Incode.
- `build()` creates the `IncodeWelcome` singleton. You can only make SDK API calls after initialization.
- `setSSLConfig()` is optional. Use it to specify SSL config for your own on-prem servers.
- `setLoggingEnabled()` is optional. Use it to enable or turn off logcat logs. Logs are enabled by default.

See [API Reference](https://developer.incode.com/docs/android-api-reference) for the complete specification of the `IncodeWelcome.Builder` and `SSLConfig`.

### Initialize from an Activity

Incode recommends initializing the SDK in your `Application` class's `onCreate()` method, as shown above. If you initialize within an `Activity` instead, guard the call with `isInitialized()` inside `onCreate()`:

```kotlin
override fun onCreate() {
    super.onCreate()
    ...
    if (!IncodeWelcome.isInitialized()) {
        IncodeWelcome.Builder(this, WELCOME_API_URL, WELCOME_API_KEY)
            .setSSLConfig(sslConfig) // optional SSL config for on-premise servers
            .setLoggingEnabled(loggingEnabled) // enable/disable logcat logs. These are enabled by default
            .build()
    }
    ...
}
```
```java
@Override
public void onCreate() {
    super.onCreate();
    ...
    if (!IncodeWelcome.isInitialized()) {
        new IncodeWelcome.Builder(this,WELCOME_API_URL,WELCOME_API_KEY)
        .setSSLConfig(sslConfig) // optional SSL config for on-premise servers
        .setLoggingEnabled(loggingEnabled) // enable/disable logcat logs. These are enabled by default
        .build();
    }
    ...
}
```

### Initialize with an External Token

You can initialize the SDK with an external token instead of an API key.

1. Initialize the SDK with `IncodeWelcome.Builder($CONTEXT, $WELCOME_API_URL)`:
   ```kotlin
   IncodeWelcome.Builder($CONTEXT, $WELCOME_API_URL)
           // additional config
           .build()
   ```
   ```java
   new IncodeWelcome.Builder($CONTEXT, $WELCOME_API_URL)
           // additional config
           .build();
   ```
2. Create a `SessionConfig` object with the external token:
   ```kotlin
   val sessionConfig = SessionConfig.Builder()
           .setExternalToken($EXTERNAL_TOKEN) // add external token here
           .build()
   ```
   ```java
   SessionConfig sessionConfig = new SessionConfig.Builder()
           .setExternalToken($EXTERNAL_TOKEN) // add external token here
           .build();
   ```

***

## Enable Test Mode

Test Mode lets you run and test the SDK on an emulator during development. Add `setTestModeEnabled(true)` to the `IncodeWelcome.Builder` chain in your `Application` class.

```kotlin
IncodeWelcome.Builder(this, WELCOME_API_URL, WELCOME_API_KEY)
    .setTestModeEnabled(true) // enable Test Mode for emulator testing
    .build()
```
```java
new IncodeWelcome.Builder(this, WELCOME_API_URL, WELCOME_API_KEY)
    .setTestModeEnabled(true) // enable Test Mode for emulator testing
    .build();
```

With Test Mode enabled, camera-dependent modules skip capture on an emulator. Instead, they show a placeholder screen and finish automatically with an emulator-detected result code:

- Document Scan, Face Match, Selfie Scan, and Video Selfie: `ResultCode.EMULATOR_DETECTED` as `resultCode`.
- ID Scan: `IdResults.RESULT_EMULATOR_DETECTED` as `frontIdResult` and `backIdResult`.

<Callout icon="❗" theme="error">
  ### Warning

  Remove `setTestModeEnabled(true)` before you build for production. Test Mode is for development only.
</Callout>

***

## What's Next

After the project successfully builds, you can begin [integration](https://developer.incode.com/docs/android-common-implementation-patterns)​.

<br />
