# How to Integrate On-Device Liveness into Your Mobile Application

{% hint style="info" %}
We recommend using server-based analyses whenever possible, as on-device ones tend to produce less accurate results.
{% endhint %}

This guide outlines the steps for integrating the Oz Liveness Mobile SDK into a customer mobile application for capturing facial videos and performing on-device liveness checks without sending any data to a server.&#x20;

The SDK implements the ready-to-use face capture user interface that is essential for seamless customer experience and accurate liveness results.

Oz Liveness Mobile SDK requires a license. License is bound to the bundle\_id of your application, e.g., `com.yourcompany.yourapp`. Issue the 1-month trial license [on our website](https://ozforensics.com/developers/try_mobile_sdk) or [email us](mailto:info@ozforensics.com) for a long-term license.&#x20;

## Android

{% stepper %}
{% step %}

### Add SDK to your project

In the build.gradle of your project, add:

```kotlin
allprojects {
    repositories {
        maven { url "https://ozforensics.jfrog.io/artifactory/main" }
    }
}
```

In the build.gradle of the module, add:

```kotlin
dependencies {
    implementation 'com.ozforensics.liveness:full:<version>'
    // You can find the version needed in the Android changelog
}
```

{% endstep %}

{% step %}

### Initialize SDK

Rename the license file to **forensics.license** and place it into the project's res/raw folder.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
OzLivenessSDK.init(
    context,
    listOf(LicenseSource.LicenseAssetId(R.raw.forensics))
)
```

{% endtab %}

{% tab title="Java" %}

```java
OzLivenessSDK.INSTANCE.init(
        context,
        Collections.singletonList(new LicenseSource.LicenseAssetId(R.raw.forensics)),
        null
);
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Add face recording

To start recording, use startActivityForResult:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val OZ_LIVENESS_REQUEST_CODE = 1
val intent = OzLivenessSDK.createStartIntent(listOf( OzAction.Blank)) startActivityForResult(intent, OZ_LIVENESS_REQUEST_CODE)
```

{% endtab %}

{% tab title="Java" %}

```java
int OZ_LIVENESS_REQUEST_CODE = 1;
Intent intent = OzLivenessSDK.INSTANCE.createStartIntent(Collections.singletonList(OzAction.Blank));
startActivityForResult(intent, OZ_LIVENESS_REQUEST_CODE);
```

{% endtab %}
{% endtabs %}

To obtain the captured video, use `onActivityResult`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == OZ_LIVENESS_REQUEST_CODE) {
            val sdkMediaResult = OzLivenessSDK.getResultFromIntent(data)
            val sdkErrorString = OzLivenessSDK.getErrorFromIntent(data)
            if (!sdkMediaResult.isNullOrEmpty()) {
                analyzeMedia(sdkMediaResult)
            } else println(sdkErrorString)
        }
    }
```

{% endtab %}

{% tab title="Java" %}

```java
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == OZ_LIVENESS_REQUEST_CODE) {
        List<OzAbstractMedia> sdkMediaResult = OzLivenessSDK.INSTANCE.getResultFromIntent(data);
        String sdkErrorString = OzLivenessSDK.INSTANCE.getErrorFromIntent(data);
        if (sdkMediaResult != null && !sdkMediaResult.isEmpty()) {
            analyzeMedia(sdkMediaResult);
        } else System.out.println(sdkErrorString);
    }
}
```

{% endtab %}
{% endtabs %}

The `sdkMediaResult` object contains the captured videos.
{% endstep %}

{% step %}

### Run analyses

To run the analyses, execute the code below. Mind that `mediaList` is an array of objects that were captured (`sdkMediaResult`) or otherwise created (media you captured on your own).

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
private fun analyzeMedia(mediaList: List<OzAbstractMedia>) {
    AnalysisRequest.Builder()
        .addAnalysis(Analysis(Analysis.Type.QUALITY, Analysis.Mode.ON_DEVICE, mediaList))
        .build()
        .run(object : AnalysisRequest.AnalysisListener {
            override fun onSuccess(result: List<OzAnalysisResult>) {
                result.forEach { 
                    println(it.resolution.name)
                    println(it.folderId)
                }
            }
            override fun onError(error: OzException) {
                error.printStackTrace()
            }
        })
} 
```

{% endtab %}

{% tab title="Java" %}

```java
private void analyzeMedia(List<OzAbstractMedia> mediaList) {
    new AnalysisRequest.Builder()
            .addAnalysis(new Analysis(Analysis.Type.QUALITY, Analysis.Mode.ON_DEVICE, mediaList, Collections.emptyMap()))
            .build()
            .run(new AnalysisRequest.AnalysisListener() {
                @Override public void onStatusChange(@NonNull AnalysisRequest.AnalysisStatus analysisStatus) {}
                @Override
                public void onSuccess(@NonNull List<OzAnalysisResult> list) {
                    for (OzAnalysisResult result: list) {
                        System.out.println(result.getResolution().name());
                        System.out.println(result.getFolderId());
                    }
                }
                @Override
                public void onError(@NonNull OzException e) { e.printStackTrace(); }
    });
}
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## iOS

{% stepper %}
{% step %}

### Add our SDK to your project

Install OZLivenessSDK.

#### [CocoaPods](https://cocoapods.org/)

To integrate OZLivenessSDK into an Xcode project, add to Podfile:

```swift
pod 'OZLivenessSDK', :git => 'https://gitlab.com/oz-forensics/oz-liveness-ios', :tag => '<version>' // You can find the version needed in  iOS changelog

```

#### SPM

Add the following package dependencies via SPM: <https://gitlab.com/oz-forensics/oz-mobile-ios-sdk> (if you need a guide on adding the package dependencies, please refer to the [Apple documentation](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app)). **OzLivenessSDK** is mandatory. Ensure you've added the **OzLivenessSDKOnDevice** file.
{% endstep %}

{% step %}

### Initialize SDK

Rename the license file to **forensics.license** and put it into the project.

```swift
OZSDK(licenseSources: [.licenseFileName("forensics.license")]) { licenseData, error in
    if let error = error {
        print(error.errorDescription)
    }
}
```

{% endstep %}

{% step %}

### Add face recording

Create a controller that will capture videos as follows:

```swift
let actions: [OZVerificationMovement] = [.selfie]
let ozLivenessVC: UIViewController = OZSDK.createVerificationVCWithDelegate(delegate, actions: actions) 
self.present(ozLivenessVC, animated: true)
```

The delegate object must implement OZLivenessDelegate protocol:

```swift
let actions: [OZVerificationMovement] = [.selfie]
let ozLivenessVC: UIViewController = OZSDK.createVerificationVCWithDelegate(delegate, actions: actions) 
self.present(ozLivenessVC, animated: true)
```

{% endstep %}

{% step %}

### Run analyses

Use AnalysisRequestBuilder to initiate the Liveness analysis.

```swift
let analysisRequest = AnalysisRequestBuilder()
let analysis = Analysis.init(
media: mediaToAnalyze, 
type: .quality, 
mode: .onDevice)
analysisRequest.uploadMedia(mediaToAnalyze)
analysisRequest.addAnalysis(analysis)
analysisRequest.run(
scenarioStateHandler: { state in }, // scenario steps progress handler
uploadProgressHandler: { (progress) in } // file upload progress handler 
) { (analysisResults : [OzAnalysisResult], error) in 
    // receive and handle analyses results here 
    for result in analysisResults {
        print(result.resolution)
        print(result.folderID)
    }
}
```

{% endstep %}
{% endstepper %}

With these steps, you are done with basic integration of Mobile SDKs. The data from the on-device analysis is not transferred anywhere, so please bear in mind you cannot access it via API or Web console. However, the internet is still required to check the license. Additionally, we recommend that you use our logging service called telemetry, as it helps a lot in investigating attacks' details. We'll provide you with credentials.

| Android [sample app](https://gitlab.com/oz-forensics/oz-liveness-android) source codes                                              | iOS [sample app](https://gitlab.com/oz-forensics/public/oz-liveness-ios-sample/-/tree/main) source codes                    |
| ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Android OzLiveness SDK [Developer Guide](https://doc.ozforensics.com/oz-knowledge/guides/developer-guide/sdk/oz-mobile-sdk/android) | iOS OzLiveness SDK [Developer Guide](https://doc.ozforensics.com/oz-knowledge/guides/developer-guide/sdk/oz-mobile-sdk/ios) |
| [Demo app](https://play.google.com/store/apps/details?id=com.ozforensics.liveness.demo\&hl=en) in PlayMarket                        | [Demo app](https://testflight.apple.com/join/mBbPQqnM) in TestFlight                                                        |

\ <br>
