# Android Liveness SDK

### Installation

To install, add the following line to your app's `build.gradle` file:

```kts
implementation("co.youverify:liveness-sdk-android:0.0.8'")
```

Add this configuration to your app module's `build.gradle.kts` file

```kts
defaultConfig {
    minSdk = 24
    targetSdk = 34
    ...
    ndk {
        abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a"))
    }
    ...
}
```

### Usage

1. Create a view model to initialize the package, here's a snippet:

```kt
private val androidSDK by viewModels<YVAndroidSDK>(factoryProducer = {
    return@viewModels object : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return YVAndroidSDK(initializers) as T
        }
    }
})
```

where `initializers` are the parameters you will be passing into the SDK, such as a collection of tasks.

> For a list of the valid options, check this out: [#initializers](#initializers "mention")

2. Start the process, like below depending on what liveness requirement your project needs, use the liveness options like so.

```kt
    private fun startCompleteTheCircleTask() {
        androidSDK.start(tasks = listOf(
            CTCTaskOptions()
        )
        )
    }

    ...
```

3. Start the UI, like so:

```kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
        ...
    setContent {
        YVLivenessTestTheme {
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Column {
                    Button(
                        onClick = { startCompleteTheCircleTask() },
                        shape = RoundedCornerShape(12.dp)

                    ) {
                        Text("Start Complete the Circle Task")
                    }
                        ......
                }

                androidSDK.StartUI()
            }
        }
    }
}
```

Full Example:

```kt
private val androidSDK by viewModels<YVAndroidSDK>(factoryProducer = {
    return@viewModels object : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return YVAndroidSDK(
              publicKey = "MY_PUBLIC_KEY",
              ...,
              onSuccess = { data -> 
                // do something with data here
              }
            ) as T
        }
    }
})

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
        ........
}

```

### Initializers

| Option               | Type     | Required | Description                                                                                                      | Default Value | Possible Values          |
| -------------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------- | ------------- | ------------------------ |
| `sandboxEnvironment` | Boolean  | No       | Sets whether session should run in sandbox or live mode                                                          | `true`        | `true`, `false`          |
| `tasks`              | List     | No       | Sets tasks that need to be performed for liveness to be confirmed                                                | null          | See tasks                |
| `user`               | SDKUser  | No       | Sets details of user for which liveness check is being performed                                                 | null          | See nested options below |
| `user.firstName`     | String   | Yes      | First name of user                                                                                               | -             | Any string               |
| `user.lastName`      | String   | No       | Last name of user                                                                                                | null          | Any string               |
| `user.email`         | String   | No       | Email of user                                                                                                    | null          | Any string               |
| `branding`           | Branding | No       | Customizes UI to fit your brand                                                                                  | null          | See nested options below |
| `branding.color`     | String   | No       | Sets your branding color                                                                                         | null          | Valid hex or RGB string  |
| `branding.logo`      | String   | No       | Sets your logo                                                                                                   | null          | Valid image link         |
| `onClose`            | Function | No       | Callback function that gets triggered when modal is closed                                                       | null          | Any valid function       |
| `onSuccess`          | Function | No       | Callback function that gets triggered when all tasks have been completed and passed. Called with completion data | null          | Any valid function       |
| `onFailure`          | Function | No       | Callback function that gets triggered when at least one task fails. Called with completion data                  | null          | Any valid function       |
| `publicKey`          | String   | Yes      | Your API key                                                                                                     | -             | Valid API Key            |

### Tasks

A task is a series of instructions for users to follow to confirm liveness. Find below a list of tasks.

> PS: We aim to frequently add to this list a variety of fun and yet intuitive ways of confirming liveness, so be on the lookout for more tasks!

#### Complete The Circle

User passes task by completing imaginary circle with head movement.

**CTCTaskOptions**

<table><thead><tr><th>Option</th><th>Type</th><th>Required</th><th width="68">Description</th><th>Default Value</th><th>Possible Values</th></tr></thead><tbody><tr><td><code>task</code></td><td>Task</td><td>Yes</td><td>Id of task</td><td>-</td><td><code>Task.COMPLETE_THE_CIRCLE</code></td></tr><tr><td><code>difficulty</code></td><td>TaskDifficulty</td><td>No</td><td>Sets difficulty of task</td><td>TaskDifficulty.Medium</td><td>.Easy, .Medium, .Hard</td></tr><tr><td><code>timeout</code></td><td>Long</td><td>No</td><td>Sets time in milliseconds after which task automatically fails</td><td><code>20000L</code></td><td>Any number in milliseconds(Long)</td></tr></tbody></table>

#### Yes Or No

User passes task by answering a list of arbitrary questions set by you with the tilting of the head; right for a `yes` and left for a `no`.

**YesOrNoTaskOptions**

| Option                   | Type           | Required | Description                                                                            | Default Value         | Possible Values                  |
| ------------------------ | -------------- | -------- | -------------------------------------------------------------------------------------- | --------------------- | -------------------------------- |
| `task`                   | Task           | Yes      | Id of task                                                                             | -                     | `Task.YES_OR_NO`                 |
| `difficulty`             | TaskDifficulty | No       | Sets difficulty of task                                                                | TaskDifficulty.Medium | .Easy, .Medium, .Hard            |
| `timeout`                | Long           | No       | Sets time in milliseconds after which task automatically fails                         | `20000L`              | Any number in milliseconds(Long) |
| `questions`              | List           | No       | A set of questions to ask user                                                         | null                  | See nested options below         |
| `questions.question`     | String         | Yes      | Question to ask user. Should be a `true` or `false` type question. Eg: "Are you ready" | -                     | Any string                       |
| `questions.answer`       | Boolean        | Yes      | Answer to the question                                                                 | -                     | `true`, `false`                  |
| `questions.errorMessage` | String         | No       | Error message to display if user gets question wrong                                   | undefined             | Any string                       |

#### Motions

User passes task by performing random motions in random sequences, which include `nodding`, `blinking` and `opening of mouth`.

**MotionTaskOptions**

| Option       | Type           | Required | Description                                                    | Default Value         | Possible Values                  |
| ------------ | -------------- | -------- | -------------------------------------------------------------- | --------------------- | -------------------------------- |
| `task`       | Task           | Yes      | Id of task                                                     | -                     | `Task.MOTIONS`                   |
| `difficulty` | TaskDifficulty | No       | Sets difficulty of task                                        | TaskDifficulty.Medium | .Easy, .Medium, .Hard            |
| `timeout`    | Long           | No       | Sets time in milliseconds after which task automatically fails | `20000L`              | Any number in milliseconds(Long) |
| `maxNods`    | Int            | No       | Maximum amount of nods a user is asked to perform              | 5                     | Any integer                      |
| `maxBlinks`  | Int            | No       | Maximum amount of nods a user is asked to perform              | 5                     | Any integer                      |

### Liveness Data

The `onSuccess` and `onFailure` callbacks (if supplied) are passed the following data:

| Option              | Type              | Description                                          |
| ------------------- | ----------------- | ---------------------------------------------------- |
| `data`              | LivenessData      | Data passed through callback                         |
| `data.faceImage`    | String            | Face Image of user performing liveness check         |
| `data.livenessClip` | String            | Video of user performing liveness check              |
| `data.passed`       | Boolean           | Indicator on whether liveness check passed or failed |
| `data.metadata`     | Map\<String, Any> | Metadata passed in during initialization             |

### Credits

This SDK is developed and maintained solely by [Youverify](https://youverify.co)
