> For the complete documentation index, see [llms.txt](https://docs.vida.id/identity-stack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vida.id/identity-stack/verify/liveness/integration/liveness-sdk/android-sdk/customization/customization-through-api.md).

# Customization through API

UI customization through the API lets your host application configure the appearance and behavior of the VIDA SDK's UI elements at runtime, without editing any resource files. This is useful when the experience needs to change dynamically - for example, per user, brand, or flow.

Customization is driven by two builders, both applied to the same `VidaLiveness` instance:

<table><thead><tr><th width="278.34375">Builder</th><th>Controls</th></tr></thead><tbody><tr><td><code>VidaUICustomizationOption</code></td><td>UI appearance &#x26; behavior - camera overlay, locale, retries, tutorial/review screens</td></tr><tr><td><code>VidaFaceDetectionOption</code></td><td>Liveness detection behavior - active liveness and gesture configuration</td></tr></tbody></table>

{% hint style="info" %}
**Note**: Looking to theme colors, fonts, and text labels instead? Those are configured through resource keys — see the [Customization through XML](/identity-stack/verify/liveness/integration/liveness-sdk/android-sdk/customization/customization-through-xml.md) page.
{% endhint %}

## UI Customization Options

Create an instance of `VidaUICustomizationOption` using its builder, set the options you need, then call `.build()`.

#### Example

<details>

<summary>Response</summary>

{% code expandable="true" %}

```java
VidaUICustomizationOption vidaUICustomizationOption =
    VidaUICustomizationOption.VidaUICustomizationOptionBuilder.newInstance()
        .setCameraOverlayStrokeWidth(6)   // Overlay line thickness
        .setOverlayShape(Shape.OVAL)      // Overlay shape
        .setLocal(locale)                 // Application language
        .setMaxRetryAttempt(3)            // Backend retry attempts
        .setShowTutorialScreen(true)      // Show / skip tutorial screen
        .setShowReviewScreen(true)        // Show / skip review screen
        .build();
```

{% endcode %}

</details>

#### Options reference

| Method                                    | Parameter                 | Description                                                                                                                                                                     |
| ----------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setCameraOverlayStrokeWidth(int width)`  | width - integer           | Thickness of the overlay lines/edges drawn on the camera UI.                                                                                                                    |
| `setOverlayShape(Shape overlayShape)`     | overlayShape - Shape enum | Shape of the camera overlay. Accepted values below.                                                                                                                             |
| `setLocal(Locale locale)`                 | locale - Locale           | Sets the application language for the SDK screens.                                                                                                                              |
| `setMaxRetryAttempt(int maxRetryAttempt)` | maxRetryAttempt - integer | Maximum backend retry attempts for liveness validation. Useful when connectivity issues or server downtime might cause a check to fail, so the SDK can retry and still succeed. |
| `setShowTutorialScreen(boolean show)`     | show - boolean            | true shows the tutorial screen that guides users through the check; false skips it.                                                                                             |
| `setShowReviewScreen(boolean show)`       | show - boolean            | true shows the review screen after capture; false skips it.                                                                                                                     |

Every method returns the current `VidaUICustomizationOptionBuilder` instance, so calls can be chained as shown above.

Accepted Shape values for `setOverlayShape()`:

| Value             | Overlay Shape |
| ----------------- | ------------- |
| `Shape.OVAL`      | Oval          |
| `Shape.CIRCLE`    | Circle        |
| `Shape.SQUARE`    | Square        |
| `Shape.RECTANGLE` | Rectangle     |

#### Applying the options

Pass the built `VidaUICustomizationOption` to the `VidaLiveness` instance using `setUICustomizationOptions(),` then initialize:

<details>

<summary>Response</summary>

{% code expandable="true" %}

```java
try {
    livenessDetection = VidaLiveness.VidaLivenessBuilder
        .newInstance(activity, livenessRequest, new VidaLivenessListener() {
            @Override
            public void onSuccess(VidaLivenessResponse vidaLivenessResponse) {
                // TODO: Update UI on success
            }
            @Override
            public void onError(int errorCode, String errorMessage,
                                VidaLivenessResponse vidaLivenessResponse) {
                // TODO: Update UI on failure
            }
            @Override
            public void onInitialized() {
                // TODO: SDK is ready
            }
        })
        .setUICustomizationOptions(vidaUICustomizationOption)
        .setDetectionOptions(vidaFaceDetectionOption)
        .build();
    livenessDetection.initialize();
} catch (VIDAException exception) {
    exception.printStackTrace();
}
```

{% endcode %}

</details>

This applies your UI customization (and detection) settings throughout the liveness flow.

## Active Liveness Options

Active liveness is configured separately, through `VidaFaceDetectionOption`, and passed to the same `VidaLiveness` instance via `setDetectionOptions()`.

{% hint style="info" %}
**Important**: Active liveness is disabled by default and must be enabled explicitly. If you enable it without configuring any gestures, the SDK falls back to `ZOOM_FACE` as the default gesture.
{% endhint %}

#### Enable active liveness

{% code expandable="true" %}

```java
setDetectionOptions(
    VidaFaceDetectionOption.VidaFaceDetectionOptionBuilder.newInstance()
        .setEnableActiveLiveness(true)
        .build()
);
```

{% endcode %}

#### Customize gestures

Use `setAllowedGestures(HashSet<Gestures> allowedGestures)` to choose which gestures the user must perform. There are two valid gesture sets:

| Gesture Set | Values                                       |
| ----------- | -------------------------------------------- |
| Zoom        | ZOOM\_FACE                                   |
| Movement    | any combination of BLINK, SMILE, SHAKE\_HEAD |

{% hint style="info" %}
**Warning**: Use either the Zoom set or the Movement set - never both. Combining `ZOOM_FACE` with BLINK / SMILE / SHAKE\_HEAD throws an exception with error code 70011.
{% endhint %}

<details>

<summary>Response</summary>

{% code expandable="true" %}

```java
HashSet<Gestures> allowedGestures = new HashSet<>();
allowedGestures.add(Gestures.BLINK);
allowedGestures.add(Gestures.SMILE);
allowedGestures.add(Gestures.SHAKE_HEAD);
setDetectionOptions(
    VidaFaceDetectionOption.VidaFaceDetectionOptionBuilder.newInstance()
        .setAllowedGestures(allowedGestures)
        .setEnableActiveLiveness(true)
        .build()
);
```

{% endcode %}

</details>

#### Minimum stable frame (optional)

`setZoomGestureMinimumStableFrame()` sets the minimum number of continuous frames that must satisfy the quality parameters. These frames are used for stable image capture and liveness analysis.

{% hint style="info" %}
**Note**: Always use the latest Android SDK version when configuring gestures.
{% endhint %}
