> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/flutter/standalone-modules/deprecated-sdks/document-detector/v7-and-above.md).

# DocumentDetector v7.x and above

## Requirements

| Flutter | Version           |
| ------- | ----------------- |
| Flutter | 1.20+             |
| Dart    | `>=2.15.0 <4.0.0` |

| Android    | Version |
| ---------- | ------- |
| minSdk     | 26      |
| compileSdk | 34      |

| iOS        | Version |
| ---------- | ------- |
| iOS Target | 13.0+   |
| Xcode      | 15.4+   |
| Swift      | 5.3.2+  |

## Native SDKs dependencies

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

```groovy

dependencies {
    // Basic
    implementation "androidx.appcompat:appcompat:1.1.0"

    // Design
    implementation "com.google.android.material:material:1.2.1"
    implementation "androidx.constraintlayout:constraintlayout:2.0.1"

    // Document detection
    implementation "org.tensorflow:tensorflow-lite:2.11.0"
    implementation "org.tensorflow:tensorflow-lite-support:0.4.3"

    // SecurityProvider
    implementation "com.google.android.gms:play-services-basement:18.3.0"

    // HTTP and deserializer
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation "com.squareup.okhttp3:okhttp:4.9.3"
    implementation "com.squareup.okhttp3:okhttp-tls:4.9.3"

    //exifInterface
    implementation "androidx.exifinterface:exifinterface:1.0.0"

    // CameraX core library using the camera2 implementation
    // The following line is optional, as the core library is included indirectly by camera-camera2
    implementation "androidx.camera:camera-core:1.1.0"
    implementation "androidx.camera:camera-camera2:1.1.0"
    // If you want to additionally use the CameraX Lifecycle library
    implementation "androidx.camera:camera-lifecycle:1.1.0"
    // If you want to additionally use the CameraX View class
    implementation "androidx.camera:camera-view:1.1.0"

    // Root Checks
    implementation "com.scottyab:rootbeer-lib:0.0.8"

    // Commons Imaging (for Images, EXIF data and so on. previously known as Apache Commons Sanselan)
    implementation "org.apache.commons:commons-imaging:1.0-alpha3"

    // Kotlin
    implementation "androidx.core:core-ktx:1.7.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.31"
}

```

{% endtab %}

{% tab title="iOS" %}

```ruby

pod "TensorFlowLiteSwift", "2.14.0"

```

{% endtab %}
{% endtabs %}

## Runtime permissions

{% tabs %}
{% tab title="Android" %}
These are the Android's runtime permissions:

| Permission              | Reason                                                                                                                                          | Required                               |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| `CAMERA`                | To capture photos of the documents                                                                                                              | Only required in camera capture stream |
| `READ_EXTERNAL_STORAGE` | To access the device external storage and select documents in the upload flow. *This permission is only required for versions lower than API33* | Only required in the upload stream     |
| {% endtab %}            |                                                                                                                                                 |                                        |

{% tab title="iOS" %}
These are the iOS's runtime permissions:

| Permission                                  | Reason                           | Required                               |
| ------------------------------------------- | -------------------------------- | -------------------------------------- |
| `Privacy - Camera Usage Description`        | To capture the document photo(s) | Only required in camera capture stream |
| `Privacy - Photo Library Usage Description` | To perform the gallery opening   | Required only in the upload stream     |
| {% endtab %}                                |                                  |                                        |
| {% endtabs %}                               |                                  |                                        |

## Platform Configurations

{% tabs %}
{% tab title="Android" %}
If your version of Gradle is earlier than 7, add these lines to your `build.gradle`.

```groovy
allprojects {
  repositories {
  ...
  maven { url 'https://repo.combateafraude.com/android/release' }
  maven { url 'https://jitpack.io' }

}}
```

If your version of Gradle is 7 or newer, add these lines to your `settings.gradle`.

```groovy
dependencyResolutionManagement {
    repositories {
        ...
        maven { url 'https://repo.combateafraude.com/android/release' }
        maven { url 'https://jitpack.io' }
    }
}
```

Add support for Java 8 (skip this code if Java 8 is enabled), and TensorFlow Model to your `build.gradle` file.

```groovy
android {

    ...

    aaptOptions {
        noCompress "tflite"
    }

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

{% hint style="info" %}
The `compileOptions` setting is required for SDK's built-in lambda functions, which were released in Java 8. The `noCompress` setting tells the compiler not to compress files with the `.tflite` extension used in the DocumentDetector.
{% endhint %}

To customize the primary color of the SDK, you need to ensure that the Material Design library is imported in your app. Add the following dependency to your build.gradle file:

```groovy
dependencies {
    ...
    implementation 'com.google.android.material:material:1.9.0'
}
```

{% endtab %}

{% tab title="iOS" %}
In the **`info.plist`** file, add the permissions below:

| Permission                                  | Reason                           | Required                               |
| ------------------------------------------- | -------------------------------- | -------------------------------------- |
| `Privacy - Camera Usage Description`        | To capture the document photo(s) | Only required in camera capture stream |
| `Privacy - Photo Library Usage Description` | To perform the gallery opening   | Required only in the upload stream     |

{% hint style="info" %}
Our SDK has translations for three languages (English, Portuguese and Spanish). To ensure that it works correctly according to the language of your operating system, add the following to your app's Info.plist (if you haven't already):

```xml
<key>CFBundleLocalizations</key>
<array>
    <string>en</string>
    <string>Portuguese (Brazil)</string>
    <string>es</string>
</array>
```

{% endhint %}

{% hint style="info" %}
Please note that the framework generated for the iOS implementation of our SDK is `static`. This is an important detail to consider during development.

Reason: The use of a static framework is due to our dependency on the `TensorFlowLiteSwift` library.

This approach was chosen to provide a better development experience, ensuring smooth integration and optimal performance.
{% endhint %}
{% endtab %}
{% endtabs %}

## Supported Documents

Currently, supported documents are:

```dart
enum DocumentType {
    rgFront, // front of RG (where the photo is located)
    rgBack, // back of RG
    rgFull, // RG opened (showing front and back together)
    cnhFront, // front of CNH (where the photo is located)
    cnhBack, // back of CNH 
    cnhFull, // CNH opened (showing front and back together)
    crlv, // CRLV
    rneFront, // front of RNE or RNM
    rneBack, // back of RNE or RNM
    passport, // passport (showing the photo and data)
    ctpsFront, // front of CTPS (where the photo is located)
    ctpsBack, // back of CTPS
    any; // allows you to send any type of document, all those mentioned above, including any other document
}
```

## Instantiating the SDK

To create a `DocumentDetector` instance, two **required parameters** must be provided:

| Parameter     | Description                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------- |
| `mobileToken` | Usage token associated with your CAF account                                                            |
| `captureFlow` | Defines the document capture flow. Create a `List<DocumentCaptureFlow>` to configure each capture step. |

### DocumentCaptureFlow

Each `DocumentCaptureFlow` element from the list will be a capture step.

The `DocumentCaptureFlow` class have the following configurations:

#### `DocumentType documentType`

Identifies which document will be requested for capture in the respective step. You can choose from the [Supported Documents](#supported-documents) list.

***

#### `InstructionalPopupSettingsAndroid? androidCustomization`

Customize the instructional popup document illustration and label for Android devices.

| Parameter                      | Description                                                                                                                                                                                                    |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String? documentLabel`        | Change the document label displayed in the popup. To customize this, you just have to provide a `String` element.                                                                                              |
| `String? documentIllustration` | Change the document illustration displayed in the popup. To customize this, you must provide the `name` of the file with the custom illustration you created in the `res/drawable` folder of your Android app. |

***

#### `InstructionalPopupSettingsIOS? iOSCustomization`

Customize the instructional popup document illustration and label for iOS devices.

| Parameter                      | Description                                                                                                                                                                                              |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String? documentLabel`        | Change the document label displayed in the popup. To customize this, you just need to provide a `String` element.                                                                                        |
| `String? documentIllustration` | Change the document illustration displayed in the popup. To customize this, you must provide the name of the `Image Set` with the custom illustration you created in the `Asset Catalog` of you iOS app. |

## Implementation Example

This is an example of how to instantiate the SDK and capture its results:

```dart
List<DocumentCaptureFlow> cnhFlow = [
    DocumentCaptureFlow(documentType: DocumentType.cnhFront),
    DocumentCaptureFlow(documentType: DocumentType.cnhBack)
];

DocumentDetector documentDetector =
    DocumentDetector(mobileToken: mobileToken, captureFlow: cnhFlow);
    
// Your SDK customization options

try {
  DocumentDetectorEvent event = await documentDetector.start();

  if (event is DocumentDetectorEventSuccess) {
// The SDK completed successfully, and the document pictures were captured.
    resultEvent = "SUCCESS";
    resultDescription = "Document Type: ${event.documentType}\n\n";
// Use `event.captures` to get the details of each document captured
    for (Capture capture in event.captures!) {
      resultDescription += "#NEW CAPTURE\n";
      resultDescription += capture.label != null
          ? "Document Label: ${capture.label!}\n"
          : "empty\n";
      resultDescription += capture.quality != null
          ? "Image Quality: ${capture.quality}\n"
          : "empty\n";
      resultDescription += capture.imagePath != null
          ? "File path on device: ${capture.imagePath!}\n"
          : "empty\n";
      resultDescription += capture.imageUrl != null
          ? "File URL: ${capture.imageUrl!.split("?")[0]}\n"
          : "empty\n";
    }
  } else if (event is DocumentDetectorEventFailure) {
// The SDK did not complete successfully, and a failure occurred during the process.
    resultEvent = "FAILURE";
    resultDescription = event.securityErrorCode != null
        ? "Security code: ${event.securityErrorCode}\n"
        : "none\n";
    resultDescription += event.errorMessage != null
        ? "Failure Description: ${event.errorMessage}\n"
        : "empty\n";
  } else if (event is DocumentDetectorEventClosed) {
// The SDK was closed, the user closed the document capture process.
    resultEvent = "CLOSED";
    resultDescription = "User closed document capture flow";
  }
} on PlatformException catch (e) {
// If an internal error occurs during the native bridge mapping, you can catch the exception this way.
  resultEvent = "Error";
  resultDescription = "Error starting DocumentDetector: ${e.message}";
}
```

### DocumentDetector options

<details>

<summary><code>setStage(CafStage stage)</code></summary>

Used to redirect the SDK to the desired environment in caf api.

**Options**

`CafStage.beta` `CafStage.prod`

**Default configuration**

`CafStage.prod`

</details>

<details>

<summary><code>setUseAnalytics(bool useAnalytics)</code></summary>

Enables/disables data gathering for analytics purposes - logs in cases of bugs and errors or fraud profile identification.

**Default configuration**

`true`

</details>

<details>

<summary><code>setPersonId(String personId)</code></summary>

Set users identifier for fraud profile identification purposes and to assist in the identification of Analytics logs in cases of bugs and errors.

</details>

<details>

<summary><code>setNetworkSettings(int requestTimeoutInSeconds)</code></summary>

Defines requests timeout. This value is represented in seconds.

**Default configuration**

By default the timeout is `60s`.

</details>

<details>

<summary><code>setUrlExpirationTime(String urlExpirationTime)</code></summary>

Sets the time the image URL will last on the server until it is expired. Expect to receive a time interval between `30m` to `30d`.

**`urlExpirationTime` example**

* `30m`: To set minutes only
* `24h`: To set only hour(s)
* `1h 10m`: To set hour(s) and minute(s)
* `10d`: To set day(s)

**Default configuration**

By default it is set to `3h`.

</details>

<details>

<summary><code>setDisplayPopup(bool displayPopup)</code></summary>

Enable/Disable the inflated popup with instructions before each document capture step.

**Default configuration**

`true`

</details>

<details>

<summary><code>setCurrentStepDoneDelayAndroid(bool enableDelay, int millisecondsDelay)</code></summary>

Delay the activity after the completion of each capture step. This value is represented in `milliseconds`.

**Default configuration**

By default there is no delay.

</details>

<details>

<summary><code>setCurrentStepDoneDelayIOS(int secondsDelay)</code></summary>

Delay the view after the completion of each capture step. This value is represented in `seconds`.

**Default configuration**

By default there is no delay.

</details>

<details>

<summary><code>setPreviewSettings(PreviewSettings previewSettings)</code></summary>

Enables/disables the document picture preview for the user, so they can check if it's all ok before send it.

Create a `PreviewSettings` element with the desired settings.

**Default configuration**

By default the preview is disabled.

**PreviewSettings options**

**`bool show`**

Enable/Disable the document capture preview feature.

***

**`String? title`**

Customimze the view title.

***

**`String? subtitle`**

Customize the view subtitle.

***

**`String? confirmButtonLabel`**

Customize the confirmation button text. This button allows the user to confirm and send the document capture.

***

**`String? retryButtonLabel`**

Customize the retry button text. This button allows the user to take another capture.

***

</details>

<details>

<summary><code>setMessageSettings(MessageSettings messageSettings)</code></summary>

Configure customized messages that are displayed during the capture and analysis process.

**MessageSettings options**

**`String? waitMessage`**

Message displayed in the opening process.

**Default**: "Please Wait…"

***

**`String? fitTheDocumentMessage`**

Message advising to fit the document to the markup.

**Default**: "Fit the document on the markup"

***

**`verifyingQualityMessage`**

Message displayed when it is verifying the capture quality.

**Default**: "Checking Quality…"

***

**`String? lowQualityDocumentMessage`**

Message displayed when the capture quality is low.

**Default**: "Ops, could not read the information. Please try again."

***

**`String? uploadingImageMessage`**

Message displayed when the capture is being uploaded on the servers.

**Default**: "Sending Image…"

***

**`String? sensorOrientationMessage`**

Message displayed when the device orientation is wrong.

**Default**: "Point the camera down"

***

**`String? sensorLuminosityMessage`**

Message displayed when the ambient brightness is lower than expected.

**Default**: "Area near you is too dark"

***

**`String? sensorStabilityMessage`**

Message displayed when the device stability parameter indicates excessive swaying.

**Default**: "Keep the device still"

***

**`String? popupDocumentSubtitleMessage`**

Message displayed in the instructional popup, providing guidelines on how to achieve the best document capture.

**Default**: "Dispose the document in a desk, centralize it on the markup and hold the automatic capture."

***

**`String? scanDocumentMessage`**

Message displayed to request a document to be present on the camera.

**Default**: "Scan a document"

***

**`String? getCloserMessage`**

Message displayed to prompt the user to bring the camera closer to the document.

**Default**: "Get closer to the document"

***

**`String? centralizeDocumentMessage`**

Message displayed to prompt the user to center the document within the camera frame.

**Default**: "Center the document"

***

**`String? moveAwayMessage`**

Message displayed to prompt the user to move the camera farther away from the document.

**Default**: "Move away from the document"

***

**`String? alignDocumentMessage`**

Message displayed to prompt the user to align the document within the camera frame.

**Default**: "Align the document"

***

**`String? turnDocumentMessage`**

Message displayed to prompt the user to rotate the document 90 degrees.

**Default**: "Turn the document 90 degrees"

***

**`String? documentCapturedMessage`**

Message displayed to notify that the document has been successfully captured.

**Default**: "Document captured"

***

**`String? holdItMessage`**

`Only for Android` Message displayed at the moment the capture is being performed.

**Default**: "Keep it that way"

***

**`String? popupConfirmButtonMessage`**

`Only for Android` Customize the confirmation button text in the instructional popup.

**Default**: "OK, understood"

***

**`String? wrongDocumentTypeMessage`**

`Only for Android` Message displayed when the document shown by the user is not the expected one for capture.

**Default**: "Ops, this document is not `${document label expected}`"

***

**`String? unsupportedDocumentMessage`**

`Only for Android` Message displayed to inform the user that the document being shown is not supported.

**Default**: "Ops, it seems that this document is not supported."

***

**`String? documentNotFoundMessage`**

`Only for Android` Message displayed to notify that no document was detected.

**Default**: "Didn't found a document."

***

</details>

<details>

<summary><code>setUploadSettings(UploadSettings uploadSettings)</code></summary>

Sets the configuration for document upload flow. By enabling this option, the user will be prompted to upload the document file instead of capturing them with the device's camera. This option also includes quality checks.

Create a `UploadSettings` element with the desired settings.

**Default configuration**

By default this feature is deactivated.

**UploadSettings options**

**`bool? compress`**

Enables/disables file compression before uploading.If enabled, it follows the Android and iOS definitions for compression quality:

[`AndroidSettings(int? compressQuality)`](#int-compressquality)

[`IOSSettings(double? captureCompressionQuality)`](#double-capturecompressionquality)

***

**`List<FileFormatAndroid>? fileFormatsAndroid`**

Defines the file format that will be accepted for upload. The options are:

`.pdf`, `.jpg`, `.jpeg`, `.png`, `.heif`.

***

**`List<FileFormatIOS>? fileFormatsIOS`**

Defines the file format that will be accepted for upload. The options are:

`.pdf`, `.jpeg`, `.png`.

***

**`int? maxFileSize`**

Specifies the maximum file size for upload, in kilobytes (kB).

`1000kB = 1MB`.

The default value is `10MB`.

***

</details>

<details>

<summary><code>setCountryCodeList(List&#x3C;CountryCodesList>? countryCodeList)</code></summary>

Restrict the acceptance of passport documents to those issued only by a specific country or a predefined list of countries.

Create a `List<CountryCodesList>` with the desired country codes.

**`countryCodeList` example**

```dart
List<CountryCodesList> countryCodeList = [
    CountryCodesList.arg,
    CountryCodesList.bra,
    CountryCodesList.usa
];
```

</details>

<details>

<summary><code>setAndroidSettings(AndroidSettings androidSettings)</code></summary>

Set Android platform exclusive settings.

Create an `AndroidSettings` element with the desired settings.

```dart
AndroidSettings androidSettings = AndroidSettings(
    captureStages: customStages,
    cameraResolution: AndroidCameraResolution.fullHd,
    compressQuality: 90,
    customStyle: "custom_style_res_name",
    feedbackColors: customFeedbackColors,
    sensorSettings: customSensorSettings,
    securitySettings: customSecuritySettings);


List<CaptureStage> customStages = [
    CaptureStage(
        captureMode: CaptureMode.automatic,
        wantSensorCheck: true,
        durationMillis: 5000),
    CaptureStage(
        captureMode: CaptureMode.manual,
        wantSensorCheck: true,
        durationMillis: null),
];

SensorSettingsAndroid customSensorSettings = SensorSettingsAndroid(
    luminositySensorSettings: 5,
    orientationSensorSettings: 3.0,
    stabilitySensorSettings: StabilitySensorSettings(
        stabilityThreshold: 0.5, stabilityDurationMillis: 2000));

SecuritySettings customSecuritySettings = SecuritySettings(
    enableGoogleServices: true,
    useAdb: false,
    useDebug: false,
    useDeveloperMode: false,
    useEmulator: false,
    useRoot: false);

FeedbackColorsAndroid customFeedbackColors = FeedbackColorsAndroid(
    defaultFeedback: "custom_default_color_res_name",
    successFeedback: "custom_success_color_res_name",
    errorFeedback: "custom_error_color_res_name");
```

**AndroidSettings options**

**`SensorSettingsAndroid? sensorSettings`**

Configure the ambient luminosity, device orientation, and stability sensor parameters to ensure the document is captured in optimal conditions.

```dart
SensorSettingsAndroid customSensorSettings = SensorSettingsAndroid(
    luminositySensorSettings: 5,
    orientationSensorSettings: 3.0,
    stabilitySensorSettings: StabilitySensorSettings(
        stabilityThreshold: 0.5, stabilityDurationMillis: 2000),
    disableLuminositySensor: false,
    disableOrientationSensor: false,
    disableStabilitySensor: false);
```

**`int? luminositySensorSettings`**

Defines threshold between acceptable/unacceptable ambient brightness.

The lower the value set, the less sensitive the orientation sensor will be.

Set `disableLuminositySensor: true` if you don't want to use this sensor.

**Default configuration**

The default settings are `5` *lx*.

***

**`double? orientationSensorSettings`**

Defines threshold between correct/incorrect device orientation.

The higher the value set, the less sensitive the orientation sensor will be.

Set `disableOrientationSensor: true` if you don't want to use this sensor.

**Default configuration**

The default setting is `3.0` *m/s²*

***

**`StabilitySensorSettings? stabilitySensorSettings`**

Defines stability sensor settings.

**`double stabilityThreshold`**

Defines the threshold between stable/unstable, in m/s² variation between the last two sensor collections. The higher the value set, the less sensitive the stability sensor will be.

***

**`int stabilityDurationMillis`**

Specifies the duration, in milliseconds, that the device must remain still to be considered stable.

Set `disableStabilitySensor: true` if you don't want to use this sensor.

**Default configuration**

The default setting is `stabilityDurationMillis: 2000` and `stabilityThreshold: 0.5`

***

**`List<CaptureStage>? captureStages`**

CaptureStage is a feature that determines the level of document capture requirements. As soon as the document capture flow starts, a timer is activated. During the defined time, the configurations specified in each of the configured stages are applied. It is possible to define a list of CaptureStages to gradually ease the document capture requirements over time. This feature exists due to the diversity of camera hardware in Android devices, preventing the user from getting stuck in the document capture flow during their onboarding.

**`captureStages` example**

```dart
List<CaptureStage> customStages = [
    CaptureStage(
        captureMode: CaptureMode.automatic,
        wantSensorCheck: true,
        durationMillis: 5000),
    CaptureStage(
        captureMode: CaptureMode.manual,
        wantSensorCheck: true,
        durationMillis: null),
];
```

**Default configuration**

The default configuration consists of the following order of `CaptureStages`:

* **CaptureStage 1**: `captureMode: CaptureMode.automatic`, `wantSensorCheck: true`, `durationMillis: 30000`;
* **CaptureStage 2**: `captureMode: CaptureMode.automatic`, `wantSensorCheck: false`, `durationMillis: 15000`;
* **CaptureStage 3**: `captureMode: CaptureMode.manual`, `wantSensorCheck: false`, `durationMillis: null`;

***

**`int? compressQuality`**

Set the quality in the compression process. By default, all captures go through compression.

The value must be between `80` and `100`, where 100 is the highest compression quality.

**Default configuration**

The default compress quality is `90`.

***

**`AndroidCameraResolution? cameraResolution`**

Set document capture resolution.

The options are `fullHd`, `quadHd` and `ultraHd`.

**Default configuration**

By default resolution is `fullHd`.

***

**`SecuritySettings? securitySettings`**

We are constantly taking actions to make the product more and more secure, mitigating a number of attacks observed in the capture process and, consequently, reducing as many possible identity frauds as possible. The SDK has some blocks that may prevent its execution in certain contexts. You can disable these validations for test purposes.

{% hint style="warning" %}
Disabling security validations is recommended for testing purposes only. For publishing your application in production, we recommend using the default settings.
{% endhint %}

To configure the security validations, you can use this options:

**`bool? enableGoogleServices`**

Allows you to enable or disable SDK features that utilize Google Services.

***

**`bool? useRoot`**

Allows you to enable or disable SDK to run in rooted devices.

***

**`bool? useEmulator`**

Allows you to enable or disable SDK to run in emulated devices.

***

**`bool? useDeveloperMode`**

Allows you to enable or disable SDK to run in devices with developer mode activated.

***

**`bool? useAdb`**

Allows you to enable or disable SDK to run in Android Debug Bridge (ADB) debugging mode.

***

**`bool? useDebug`**

Allows you to enable or disable SDK to run in a debug mode application.

***

**Default configuration**

```dart
SecuritySettings securitySettings = SecuritySettings(
    enableGoogleServices: true,
    useAdb: false,
    useDebug: false,
    useDeveloperMode: false,
    useEmulator: false,
    useRoot: false);
```

***

**`String? customStyle`**

Define your custom app style to change the primary color of the SDK.

To customize, create a `style.xml` resource file in your app and add this style fragment to it, replacing the values inside the placeholders:

```xml
<resources>
  <style name={style_name} parent={parent_name}>
    <item name="colorPrimary">{custom_color_hex}</item>
  </style>
</resources>
```

***

**`FeedbackColorsAndroid? feedbackColors`**

Customize the UI feedback colors to be displayed.

To customize the UI feedback colors in your app, follow these steps:

* Create a `colors.xml` resource file in your app's `res/values` directory.
* Define the colors for the different types of feedback: `default`, `success`, and `error`.

Here is an improved version of the `colors.xml` file with placeholders for the color hex values:

```xml
<resources>
 <color name="feedback_default">{default_color}</color>
 <color name="feedback_success">{success_color}</color>
 <color name="feedback_error">{error_color}</color>
</resources>
```

</details>

<details>

<summary><code>setIOSSettings(IOSSettings iosSettings)</code></summary>

Set iOS platform exclusive settings.

Create an `IOSSettings` element with the desired settings.

```dart
IOSSettings iosSettings = IOSSettings(
    cameraResolution: IOSCameraResolution.fullHd,
    captureCompressionQuality: 0.90,
    sensorSettings: customSensorSettings,
    enableMultiLanguage: true,
    enableManualCapture: false,
    manualCaptureActivationDelay: 45,
    customLayout: customLayout);

SensorSettingsIOS customSensorSettings = SensorSettingsIOS(
    luminositySensorSettings: -3,
    orientationSensorSettings: 0.3,
    stabilitySensorSettings: 0.3);

CustomLayoutIOS customLayout = CustomLayoutIOS(
    feedbackColors: FeedbackColorsIOS(
        defaultFeedback: "#000000",
        successFeedback: "#e21b45",
        errorFeedback: "#0baa43"),
    primaryColor: "#34D690");
```

**`SensorSettingsIOS? sensorSettings`**

Configure the ambient luminosity, device orientation, and stability sensor threshold parameters to ensure the document is captured in optimal conditions.

```dart
SensorSettingsIOS customSensorSettings = SensorSettingsIOS(
    luminositySensorSettings: -3,
    orientationSensorSettings: 0.3,
    stabilitySensorSettings: 0.3);
```

**`double? luminositySensorSettings`**

Defines threshold between acceptable/unacceptable ambient brightness.

The lower the value set, the less sensitive the orientation sensor will be.

**Default configuration**

The default settings is `-3`.

***

**`double? orientationSensorSettings`**

Defines the threshold between correct/incorrect device orientation based on the variation of the last two accelerometer sensor readings collected from the device.

The higher the value set, the less sensitive the orientation sensor will be.

**Default configuration**

The default setting is `0.3`.

***

**`double? stabilitySensorSettings`**

Defines the threshold between stable/unstable device based on the variation of the last two gyro sensor readings collected from the device.

The higher the value set, the less sensitive the stability sensor will be.

**Default configuration**

The default setting is `0.3`.

***

**`double? captureCompressionQuality`**

Set the quality in the compression process. By default, all captures go through compression. The method expects values between `0.8` and `1.0` as a parameter, where `1.0` is the best compression quality.

**Default configuration**

The default compression quality is `0.9`.

***

**`bool? enableManualCapture`**

Enable the manual capture option. With this configuration `enabled`, you can specify the time - in seconds - until manual capture is activated using the [`manualCaptureActivationDelay`](#int-manualcaptureactivationdelay) parameter.

**Default configuration**

By default the manual capture is set to `false`.

For devices below iOS 13 this feature is always `true`, there is no automatic capture.

***

**`int? manualCaptureActivationDelay`**

Set the time delay to enable manual capture option for the user.

To enable the manual capture feature, use `enableManualCapture: true` parameter.

**Default configuration**

By default the timer is set to `45` seconds.

***

**`bool? enableMultiLanguage`**

This configuration enables or disables multi-language support (English, Spanish, Brazilian Portuguese). If disabled, the language will default to Brazilian Portuguese.

**Default configuration**

`true`

***

**`IOSCameraResolution? cameraResolution`**

Set document capture resolution.

The options are `fullHd` and `ultraHd`.

**Default configuration**

By default resolution is `fullHd`.

***

**`CustomLayoutIOS? customLayout`**

Customize you iOS app layout settings.

Within this options you can change the buttons color, UI feedbacks color and app font.

```dart
CustomLayoutIOS customLayout = CustomLayoutIOS(
    feedbackColors: FeedbackColorsIOS(
        defaultFeedback: "#000000",
        successFeedback: "#e21b45",
        errorFeedback: "#0baa43"),
    primaryColor: "#34D690");
```

</details>

## DocumentDetectorEvent Results

`DocumentDetectorEvent` is an abstract class representing different types of events.

It is used to create an instance of one of the event subclasses based on a map input, which comes from the SDK's result.

Depending on the event type, it creates an instance of either `DocumentDetectorEventClosed`, `DocumentDetectorEventSuccess`, or `DocumentDetectorEventFailure`. If the event is not recognized, it throws an internal exception.

This setup allows for a structured and type-safe way to handle different outcomes of the document capture process in the SDK.

```dart
try {
  DocumentDetectorEvent event = await documentDetector.start();

  if (event is DocumentDetectorEventSuccess) {
// The SDK completed successfully, and the document pictures were captured.
    for (Capture capture in event.captures!) {
// Use `event.captures` to get the details of each document captured         
    }
  } else if (event is DocumentDetectorEventFailure) {
// The SDK did not complete successfully, and a failure occurred during the process.
  } else if (event is DocumentDetectorEventClosed) {
// The SDK was closed, the user closed the document capture process.
  }
} on PlatformException catch (e) {
// If an internal error occurs during the native bridge mapping, you can catch the exception this way.
}
```

### `DocumentDetectorEventClosed`

This class represents an event where the document capture was closed by the user, either by pressing the close button at the top right, or sending the app to the background.

### `DocumentDetectorEventSuccess`

This class represents a successful document capture event. The user document has been successfully captured, and the URLs for download the captures have been returned. It includes:

<details>

<summary><code>List&#x3C;Capture>? captures</code></summary>

A list of `Capture` objects representing the captured documents. `Capture` includes:

**`String? imagePath`**

Full path of the image file on the user's device.

***

**`String? imageUrl`**

URL of the document file on the Caf's server. This URL has an expiry time, which can be set with the [`setUrlExpirationTime`](#urlexpirationtime-example) method.

***

**`String? label`**

Label of the captured document, for example: `cnh_front`, `rg_back`, `passport`...

***

**`double? quality`**

Quality inferred by the document quality algorithm, varying between `0` and `5`.

***

</details>

#### `String? documentType`

The type of the document captured

#### `String? trackingId`

An ID for tracking the capture execution.

### `DocumentDetectorEventFailure`

This class represents a failure in the document capture process. The user document hasn't been successfully captured, the `errorType` and `errorMessage` parameter contains the failure reason. It includes:

#### `String? errorType`

Information on the type of error returned by the SDK. Below are the types of errors and their causes:

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

| Type                 | Reason                                                                                           | Example                                                                                                                                     |
| -------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `AvailabilityReason` | The SDK is not yet available for use. The `errorMessage` parameter will bring more instructions. | The device's internal storage is full when installing the app, and the face detection template cannot be installed together.                |
| `InvalidTokenReason` | The token entered is not valid for the corresponding product.                                    | If you are using an expired or non-existent token.                                                                                          |
| `LibraryReason`      | When an SDK internal library cannot be started.                                                  | Forgetting to set the `aaptOptions` [noCompress](#platform-configurations) configuration will lead to this failure in the DocumentDetector. |
| `NetworkReason`      | Internet connection failure.                                                                     | User was without internet during the SDK execution.                                                                                         |
| `PermissionReason`   | You are missing some mandatory permission to run the SDK.                                        | Start SDK without camera permission granted.                                                                                                |
| `SecurityReason`     | When the SDK cannot be started due to a security reason.                                         | When the device is rooted. See [security error code](#int-securityerrorcode) for more reasons.                                              |
| `ServerReason`       | When an SDK request receives a status code of failure.                                           | If an internal API is unstable.                                                                                                             |
| `StorageReason`      | There is no space on the user device's internal storage.                                         | When there is no space on the internal storage while capturing the document photo.                                                          |
| {% endtab %}         |                                                                                                  |                                                                                                                                             |

{% tab title="iOS" %}

| Type                 | Reason                                                        | Example                                                                            |
| -------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `InvalidTokenReason` | The token entered is not valid for the corresponding product. | If you are using an expired or non-existent token.                                 |
| `NetworkReason`      | Internet connection failure.                                  | User was without internet during the SDK execution.                                |
| `PermissionReason`   | You are missing some mandatory permission to run the SDK.     | Start SDK without camera permission granted.                                       |
| `ServerReason`       | When an SDK request receives a status code of failure.        | If an internal API is unstable.                                                    |
| `StorageReason`      | There is no space on the user device's internal storage.      | When there is no space on the internal storage while capturing the document photo. |
| {% endtab %}         |                                                               |                                                                                    |
| {% endtabs %}        |                                                               |                                                                                    |

#### `String? errorMessage`

A message describing the error.

#### `int? securityErrorCode`

An error code specific to Android, indicating the type of security validation failure:

* `100` - blocking emulated devices;
* `200` - blocking rooted devices;
* `300` - blocking devices with developer options enabled;
* `400` - blocking devices with ADB enabled;
* `500` - blocking devices with debugging enabled;


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/flutter/standalone-modules/deprecated-sdks/document-detector/v7-and-above.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
