# Installation

Install the Incode Onboarding Cordova Plugin and complete per-platform setup for Android and iOS.

## Prerequisites

- **Node.js** version 18 or later, for the Cordova CLI and your app.
- **Cordova CLI** version 11 or later. Install with `npm install -g cordova`.
- **Android Studio / SDK**: API 23 or later, `compileSdk` 35, Java 11 or later. Required for Android builds.
- **Xcode** with iOS 13 or later target. Required for iOS builds (macOS only).
- **Incode API credentials**: API key and base URL, provided by Incode.
- **GitHub personal access token** with `read:packages` scope, for Incode's Android Maven repository.

## Install the plugin

```bash
cordova plugin add https://github.com/Incode-Technologies-Example-Repos/CordovaPluginReleases.git#release/[VERSION]
```

For the NFC variant (NFC-capable hardware required):

```bash
cordova plugin add "https://github.com/Incode-Technologies-Example-Repos/CordovaPluginReleases.git#release/[VERSION]-nfc"
```

The SDK uses the camera to capture ID and face, so add the camera plugin:

```bash
cordova plugin add cordova-plugin-camera
```

If you use the geolocation module, add the geolocation plugin as well:

```bash
cordova plugin add cordova-plugin-geolocation
```

Then add the platforms you target. Pin the platform versions confirmed compatible with the SDK rather than relying on defaults:

```bash
cordova platform add android@^14.0.1
cordova platform add ios@^7.1.1   # macOS only
```

## Android setup

Android resolves the Incode native SDK from Incode's GitHub Maven package repository, which requires authentication:

1. Create a GitHub username and ask your Incode representative for a GitHub personal access token.&#x20;
2. Expose the username and token to the build as `GITHUB_USERNAME` and `GITHUB_TOKEN`, either as environment variables or as Gradle properties (`github_username` / `github_token`).

The Maven repository that hosts the native dependency is:

```
https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages
```

Add a hook within the `config.xml` file inside `widget`, after your `platform` element. It will be triggered after platform is added:&#x20;

```xml
<hook type="after_platform_add" src="hooks/after_platform_add/add-incode-maven-repo.js" />
```

`add-incode-maven-repo.js` content that can be reused:

```javascript
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

const repoBlock = `maven {
    url = uri("https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages")
     credentials {
        username = project.findProperty("github_username") ?: System.getenv("GITHUB_USERNAME")
        password = project.findProperty("github_token") ?: System.getenv("GITHUB_TOKEN")
    }
}`;

function removeIncodeMavenBlocks(block) {
    let idx = 0;
    while (true) {
        const mavenIndex = block.indexOf('maven {', idx);
        if (mavenIndex === -1) break;
        // Only consider blocks containing the Incode repo URL
        const urlIdx = block.indexOf('repo.incode.com/artifactory/libs-incode-welcome', mavenIndex);
        if (urlIdx === -1) {
            idx = mavenIndex + 7;
            continue;
        }
        // Find the matching closing brace for maven { ... }
        let braceCount = 0;
        let endIdx = mavenIndex;
        let found = false;
        for (; endIdx < block.length; endIdx++) {
            if (block[endIdx] === '{') braceCount++;
            else if (block[endIdx] === '}') braceCount--;
            if (braceCount === 0 && endIdx > mavenIndex) {
                found = true;
                break;
            }
        }
        if (found) {
            block = block.slice(0, mavenIndex) + block.slice(endIdx + 1);
            idx = mavenIndex; // Continue searching after removed block
        } else {
            break; // Malformed, stop
        }
    }
    return block;
}

function insertRepoFirst(block) {
    block = removeIncodeMavenBlocks(block);
    return block.replace(/repositories\s*\{/, match => `${match}\n${repoBlock}\n`);
}

function patchGradle(context) {
    const projectRoot = context.opts && context.opts.projectRoot ? context.opts.projectRoot : process.cwd();
    const appGradlePath = path.join(projectRoot, 'platforms/android/app/build.gradle');
    if (!fs.existsSync(appGradlePath)) {
        console.log('app/build.gradle not found:', appGradlePath);
        return;
    }
    let appGradle = fs.readFileSync(appGradlePath, 'utf8');

    // Patch buildscript
    appGradle = appGradle.replace(/(buildscript\s*\{[\s\S]*?)(\n\s*dependencies\s*\{)/, (match, p1, p2) => {
        let beforeDeps = p1;
        if (/repositories\s*\{/.test(beforeDeps)) {
            beforeDeps = insertRepoFirst(beforeDeps);
        } else {
            beforeDeps = beforeDeps.replace(/buildscript\s*\{/, m => `${m}\n    repositories {\n${repoBlock}\n    }\n`);
        }
        return beforeDeps + p2;
    });

    // Patch allprojects
    appGradle = appGradle.replace(/(allprojects\s*\{[\s\S]*?)(\n\s*task |\n\s*ext |\n\s*android |\n\s*\/\*|$)/, (match, p1, p2) => {
        let beforeNext = p1;
        if (/repositories\s*\{/.test(beforeNext)) {
            beforeNext = insertRepoFirst(beforeNext);
        } else {
            beforeNext = beforeNext.replace(/allprojects\s*\{/, m => `${m}\n    repositories {\n${repoBlock}\n    }\n`);
        }
        return beforeNext + p2;
    });

    fs.writeFileSync(appGradlePath, appGradle, 'utf8');
}

// Cordova will call as a function during the build, but allow running directly for manual testing
module.exports = patchGradle;
if (require.main === module) {
    patchGradle({ opts: { projectRoot: process.cwd() } });
}
```

## iOS setup

iOS native dependencies are managed through CocoaPods and are installed when you add the iOS platform. If pod installation fails, run `pod repo update` and re-add the platform:

```bash
cordova platform rm ios && cordova platform add ios@^7.1.1
```

## Initialize the SDK

On startup, call `initializeSDK()` with your Incode API key and base URL:

```js
cordova.exec(
  function () { console.log("SDK ready"); },
  function (err) { console.log("Init error:", err); },
  "Cplugin",
  "initializeSDK",
  [
    "YOUR_API_KEY",              // apiKey
    "https://your.api.url",      // apiUrl
    "true",                      // loggingEnabled
    "false",                     // testMode
    "false",                     // isExternalTokenEnabled
    "experimentV2",              // clientExperimentId (opts iOS into V2 UI; use null for V1)
    "https://your.e2ee.api.url", // e2eeUrl
    { enabled: false, forceSSLPinning: false } // sslPinningConfig
  ]
);
```

Keep all credentials out of source control. For the full argument breakdown, see the [API Reference](api-reference).
