# MyID Android SDK

## Table of contents

- [Changelog](CHANGELOG.md)
- [Getting started](#getting-started)
  - [Before you begin](#11-before-you-begin)
  - [Setup MyID Android SDK](#12-setup-myid-android-sdk)
  - [Permissions](#13-permissions)
- [Usage](#usage)
  - [Methods](#11-methods)
  - [Handling callbacks](#12-handling-callbacks)
- [SDK error codes](#sdk-error-codes)
- [UI customization](CUSTOMIZATION.md)

## Getting started

### 1.1 Before you begin

Install or update Android Studio to its latest version.

The SDK supports API level 21 and above

Make sure that your app meets the following requirements:

- `minSdkVersion = 21`
- `targetSdkVersion = 34`
- `Kotlin = 1.8.10+`
- `android.useAndroidX = true`

``` gradle
compileOptions {
  sourceCompatibility JavaVersion.VERSION_1_8
  targetCompatibility JavaVersion.VERSION_1_8
}
```

### 1.2 Setup MyID Android SDK

#### Step 1: Add the Repository

First, add the Artifactory repository to the repositories block of your module's **_build.gradle_** file:

```gradle
repositories {
  maven { url "https://artifactory.aigroup.uz:443/artifactory/myid" }
}
```

#### Step 2: Add the Dependency

Next, add the SDK dependency to the dependencies block:

```gradle
dependencies {
  implementation("uz.myid.sdk.capture:myid-capture-sdk:2.3.3")
}
```

If you are using Huawei devices, Flutter or an environment that does not support Google Play Services, use the bundled version of the SDK:

```gradle
dependencies {
  implementation("uz.myid.sdk.capture:myid-capture-sdk-bundled:2.3.3")
}
```

After synchronization, You should be able to access to SDK classes from your source code.

### 1.3 Permissions

Add following lines to the **_AndroidManifest.xml_**:

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

## Usage

### With Activity Result API

``` kotlin
class ExampleActivity : AppCompatActivity(), MyIdResultListener {

    private val client = MyIdClient()

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

    private fun startMyId() {
        val config = MyIdConfig.builder(clientId = /* Your client id */)
            .withClientHash(/* Your clientHash */, /* Your clientHashId */)
            .withPassportData(passportData)
            .withBirthDate(dateOfBirth)
            .withBuildMode(MyIdBuildMode.PRODUCTION)
            .build()

        val intent = client.createIntent(activity = this, config)
        result.launch(intent)
    }

    private val result = takeUserResult(listener = this)
}
```

### With `onActivityResult` method

``` kotlin
class ExampleActivity : AppCompatActivity(), MyIdResultListener {

    private val client = MyIdClient()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        startMyId()
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        client.handleActivityResult(resultCode, this)
    }

    private fun startMyId() {
        val config = MyIdConfig.builder(clientId = /* Your client id */)
            .withClientHash(/* Your clientHash */, /* Your clientHashId */)
            .withPassportData(passportData)
            .withBirthDate(dateOfBirth)
            .withBuildMode(MyIdBuildMode.PRODUCTION)
            .build()

        /*
           Start the flow. 1 should be your request code (customize as needed).
           Must be an Activity or Fragment (support library).
           This request code will be important for you on onActivityResult() to identify the MyIdResultListener.
        */
        client.startActivityForResult(this, 1, config)
    }
}
```

### 1.1 Methods

Method | Notes | Default
--- | --- | ---
`withClientHash(clientHash: String, clientHashId: String)` | Provided by MyID sales team | Mandatory, if using withEntryType(MyIdEntryType.AUTH)
`withPassportData(value: String)` | Passport serial number or PINFL data | Optional
`withBirthDate(value: String)` | Date of birth. Format: `dd.MM.yyyy` | Optional
`withMinAge(value: Int)` | To set a specific minimum age to use MyID service | 16
`withSdkHash(value: String)` | 32 characters long string (Note 1.2) | Optional
`withExternalId(value: String)` | 36 characters long. Should match with UUID4 regex (Note 1.3) | Optional
`withThreshold(value: Float)` | The value can be in the range of `0.55` - `0.99` | 0.55
`withBuildMode(value: MyIdBuildMode)` | Build mode (Note 1.4) | MyIdBuildMode.PRODUCTION
`withEntryType(value: MyIdEntryType)` | Customizing the SDK Entry types (Note 1.5) | MyIdEntryType.AUTH
`withResidency(value: MyIdResidentType)` | To set a specific resident type | MyIdResidentType.RESIDENT
`withLocale(value: Locale)` | To set a specific locale | Locale("uz")
`withCameraShape(value: MyIdCameraShape)` | To set a specific camera shape (Note 1.6) | MyIdCameraShape.CIRCLE
`withResolution(value: MyIdResolution)` | To set a specific camera resolution | MyIdResolution.RESOLUTION_480
`withScreenOrientation(value: MyIdScreenOrientation)` | To set a specific screen orientation | MyIdScreenOrientation.FULL
`withImageFormat(value: MyIdImageFormat)` | To set a specific image format | MyIdImageFormat.PNG
`withOrganizationDetails(value: MyIdOrganizationDetails)` | Custom Organization Details | Optional

**Note 1.1.** You can customize the screen for entering passport data and date of birth in your
application, in which case you can pass these parameters during initialization to the SDK, otherwise
the SDK requires the input of passport data and date of birth for user identification.

**Note 1.2.** If the `sdk_hash` is empty, blank or string with length other than 32 has been
provided, we will continue showing the credentials screen.

**Note 1.3.** If the `externalId` is not empty, has a length of 36 characters and corresponds to the
regular expression UUID4, we will display a [recommendation](images/screen01.jpg) screen in case the
sdk detects a blurry photo.

**Note 1.4.** `MyIdBuildMode` contains **DEBUG** and **PRODUCTION** modes.

- **DEBUG** is used to sandbox.
- **PRODUCTION** is used to production.

**Note 1.5.** `MyIdEntryType` contains **AUTH** and **FACE** types.

- **AUTH** is used to identify the user through the MyID services.
- **FACE** is used to detect a face and returns a picture (bitmap).

**Note 1.6.** `MyIdCameraShape` contains **[CIRCLE](images/screen03.jpg)**
and **[ELLIPSE](images/screen04.jpg)** types.

### 1.2 Handling callbacks

```kotlin
val resultListener: MyIdResultListener = object : MyIdResultListener {
  override fun onSuccess(result: MyIdResult) {
    // Get face bitmap and result code

    val bitmap = result.getGraphicFieldImageByType(MyIdGraphicFieldType.FACE_PORTRAIT)
    val code = result.code
    val comparison = result.comparison
  }

  override fun onUserExited() {
    // User left the SDK
  }

  override fun onError(e: MyIdException) {
    // Get error message and code:

    val message = e.message
    val code = e.code
  }
}
```

| Attribute     |    Notes    |
| -----|-------|
| `onSuccess` | `MyIdResult` contains information about the face captures made during the flow, result code and comparison value. |
| `onUserExited` | User left the SDK flow without completing it. |
| `onError` | Some error happened. `MyIdException` contains information about the error message and code |

## SDK error codes

The error code in the following list may appear during the call of SDK. The list below is for your
reference.

| Code |      Error message
|:----:|:-------------
|  2   |  Паспортные данные введены неправильно
|  3   |  Не удалось подтвердить жизненность
|  4   |  Не удалось распознать
|  5   |  Внешний сервис недоступен или работает некорректно
|  6   |  Запрашиваемый пользовател скончался
|  7   |  Фото с ресурсов не получено
|  8   |  Внутренняя ошибка MyID
|  9   |  Срок выполнения задачи истек
|  10  |  Срок ожидания задачи в очереди истек
|  11  |  Сервис MyID не может обработать запрос. Попробуйте повторить позже
|  12  |  Сервис MyID не может обработать запрос. Попробуйте повторить позже
|  13  |  Сервис MyID не может обработать запрос. Попробуйте повторить позже
|  14  |  Не удалось подтвердить жизненность. Некорректная фотография
|  15  |  Сервис MyID не может обработать запрос. Попробуйте повторить позже
|  16  |  Сервис MyID не может обработать запрос. Попробуйте повторить позже
|  17  |  Не удалось распознать. Некорректная фотография
|  18  |  Сервис проверки жизненности не может обработать запрос
|  19  |  Сервис распознования не может обработать запрос
|  20  |  Размытая фотография
|  21  |  Лицо не полностью изображено
|  22  |  Обнаружено несколько лиц
|  23  |  Представленное изображение в градациях серого, требуется цветное изображение
|  24  |  Обнаружены затемненные очки
|  25  |  Тип фотографии не поддерживается
|  26  |  Глаза закрыты либо не видны
|  27  |  Обнаружено вращение головы
|  28  |  Не удалось обнаружить все ориентиры
| 101  |  Непредвиденная ошибка
| 102  |  Доступ к камере запрещен
| 103  |  Ошибка при получении данных с сервера
| 120  |  Размытое фото обнаружено в SDK
