> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bright-sdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bright SDK for Unity - Integration Guide

> This guide is for developers who want to monetize Unity applications with Bright SDK.

export const CustomConsent = ({platform}) => <>
    <Warning>
      <strong>Subject to Bright SDK approval.</strong> Please contact Bright SDK before implementing to get pre-approved.
    </Warning>

    <h3>Design Requirements</h3>
    <p>Your custom consent screen must include the following mandatory elements:</p>

    <p><strong><u>Mandatory text:</u></strong></p>
    <pre><code className="language-text">{`"To [Benefit to user], please allow Web Indexing by Bright Data to use your device's free resources and IP address to download public web data from the Internet. None of your personal information is collected, except your IP address. Bright Data does not track you."`}</code></pre>

    <p><strong><u>Required links:</u></strong></p>
    <table>
      <thead>
        <tr>
          <th>Text</th>
          <th>URL</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Bright Data</td>
          <td><a href="https://www.brightdata.com">https://www.brightdata.com</a></td>
        </tr>
        <tr>
          <td>Privacy Policy</td>
          <td><a href="https://bright-sdk.com/privacy-policy">https://bright-sdk.com/privacy-policy</a></td>
        </tr>
        <tr>
          <td>End User License Agreement</td>
          <td><a href="https://bright-sdk.com/EULA">https://bright-sdk.com/EULA</a></td>
        </tr>
      </tbody>
    </table>

    <p><strong>For Android TV:</strong></p>
    <p>Replace links with:</p>
    
    <pre><code className="language-text">{`Scan the QR Code to learn more about Bright Data policy and ethical usage`}</code></pre>

    <p>Use your own branded QR code or a hosted version pointing to: <a href="https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing">https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing</a></p>

    <p><strong><u>Interactive element:</u></strong></p>
    <ul>
      <li>Tapping "public web data" must open a popup with additional information.
      <pre><code className="language-markdown">{`"Bright Data does not track you.Your IP address WILL be used for cases such as: 
    Support academic research 
    Help brands track sites selling fake products 
    Collect public web data like product prices and reviews 
    Aggregate travel information like flights and hotel prices "`}</code></pre>
      </li>
    </ul>

    <p><strong><u>Translations:</u></strong></p>
    <ul>
      <li>If you wish to translate your screen, use only the provided official translations. Contact your partnership manager for any missing languages.</li>
    </ul>

    {platform === "android" && <>
        <h3>Integration Code</h3>
        
        <p><strong>Skip the default consent screen:</strong></p>
        <pre><code>{`Settings settings = new Settings(context);
settings.setSkipConsent(true);`}</code></pre>

        <p><strong>When showing your custom screen, notify the SDK:</strong></p>
        <pre><code>{`BrightApi.reportConsentShown(context);`}</code></pre>

        <p><strong>Opt-in button (e.g., "I Agree"):</strong></p>
        <pre><code>{`BrightApi.externalOptIn(context);`}</code></pre>

        <p><strong>Opt-out button (e.g., "I Disagree"):</strong></p>
        <pre><code>{`BrightApi.optOut(context);`}</code></pre>

        <p><strong>If the user pressed back without making a choice:</strong><br />
        (Only call this if you allow closing via the back button)</p>
        <pre><code>{`BrightApi.reportConsentBackPress(context);`}</code></pre>

        <Warning>
          If you disable closing the consent screen via the back button, do <strong>not</strong> call <code>reportConsentBackPress</code>.
        </Warning>
      </>}

    {platform === "unity" && <>
        <h3>Integration Code</h3>

        <p><strong>Skip the default consent screen:</strong></p>
        <pre><code>{`// Create a Settings object
AndroidJavaObject settings = new AndroidJavaObject("com.android.eapx.Settings", currentActivity);
// Prevent consent screen from showing automatically
settings.Call("setSkipConsent", true);`}</code></pre>

        <p><strong>When showing your custom screen, notify the SDK:</strong></p>
        <pre><code>{`brightApi.CallStatic("reportConsentShown", currentActivity);`}</code></pre>

        <p><strong>Opt-in button (e.g., "I Agree"):</strong></p>
        <pre><code>{`brightApi.CallStatic("externalOptIn", currentActivity);`}</code></pre>

        <p><strong>Opt-out button (e.g., "I Disagree"):</strong></p>
        <pre><code>{`brightApi.CallStatic("optOut", currentActivity);`}</code></pre>

        <p><strong>If the user pressed back without making a choice:</strong><br />
        (Only call this if you allow closing via the back button)</p>
        <pre><code>{`brightApi.CallStatic("reportConsentBackPress", currentActivity);`}</code></pre>

        <Warning>
          If you disable closing the consent screen via the back button, do <strong>not</strong> call <code>reportConsentBackPress</code>.
        </Warning>
      </>}

    <p>See below some examples of possible custom consent screens:</p>

    <img src="/snippets/image/android_unity_consent_2.png" alt="Popup example" width="400" />

    <img src="/snippets/image/android_unity_consent_3.png" alt="Popup example" width="400" />

    <img src="/snippets/image/android_unity_consent_4.png" alt="Popup example" width="400" />

    <img src="/snippets/image/android_unity_consent_5.png" alt="Popup example" width="400" />
  </>;

<Note>
  For the full Android integration reference, see the [Android SDK Integration Guide](https://docs.bright-sdk.com/integration-guides/android-sdk). This document covers only Unity-specific steps and should be used in conjunction with that guide.
</Note>

### Requirements

* [Latest](https://bright-sdk.com/cp/docs/sdk/android) Bright SDK AAR for Android.
* Unity Editor (latest recommended).
* Android build support installed in Unity.

### Important Notes

* Users must **always** voluntarily decide to opt in after seeing the consent screen, and must **always** have an easy way to opt out.
* Bright Data reviews SDK integration after initial release and regularly thereafter. **Your account will be terminated if you violate the guidelines in this document**.
* Bright Data recommends offering value in exchange for opting in (e.g., fewer ads, bonus coins, premium features). However, simply asking for user support is also acceptable.
* **Do not upload your APK with Bright SDK to the Google Play Store without prior approval.**

<Steps>
  <Step title="Create App ID on Dashboard" titleSize="h3">
    If you haven't done this yet, log in to [your dashboard](https://bright-sdk.com/cp/apps) and create your app ID first.
  </Step>

  <Step title="Install SDK Files" titleSize="h3">
    You can set up the Bright SDK AAR in your Unity project in two ways:

    * [**Using the Bright SDK Unity Plugin**](https://github.com/BrightSDK/unity-plugin) <Badge color="green">Recommended</Badge> - automatically downloads, extracts, and places the latest `bright_sdk.aar` into the correct Unity directory before every build.
    * **Manually** - download the AAR from the dashboard and copy it yourself into the project.

    Either way, you will still need to configure your Gradle files and add the SDK initialization code to your app.

    <AccordionGroup>
      <Accordion title={<span>Option A - Using the Unity Plugin <Badge color="green" size="md">Recommended</Badge></span>}>
        Install the plugin by following the [Bright SDK Unity Plugin guide](https://github.com/BrightSDK/unity-plugin).

        The plugin will:

        * Fetch the latest `bright_sdk.aar` via the authenticated BrightSDK API (`SDK_API_KEY`) and place it into `Assets/Plugins/Android/`.
        * Cache the file locally to avoid redundant re-downloads.
        * Run automatically on every build (**File → Build Settings → Build**).

        Once the plugin is set up, skip to **Step 3 - Add Main Gradle and Gradle Properties Files**.
      </Accordion>

      <Accordion title="Option B - Manual">
        Download the latest Bright SDK AAR using the [Bright SDK downloader](https://brightsdk.github.io/bright-sdk-downloader-rs/).

        In the `Assets` folder, create a sub-folder named `Plugins` and inside it a sub-folder named `Android`:

        ```text theme={null}
        Assets > Plugins > Android
        ```

        Drag the `bright_sdk.aar` file into the `Android` folder.

        <img src="https://mintcdn.com/brightdata-31a14106/a71ZLdHh7QHMg9mg/integration-guides/image/unity_integration_guide_1.png?fit=max&auto=format&n=a71ZLdHh7QHMg9mg&q=85&s=ae966cb9aafac71517970f8f05bde54a" alt="Drag AAR file into Android folder" width="400" data-path="integration-guides/image/unity_integration_guide_1.png" />
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Add Main Gradle and Gradle Properties Files" titleSize="h3">
    <Note>
      Regardless of which option you chose above, the following Gradle steps must be done manually.
    </Note>

    Enable the following options in Unity:

    * **Editor → Player → Publishing Settings → Build → Custom Main Gradle Template**
    * **Editor → Player → Publishing Settings → Build → Custom Gradle Properties Template**

    This will create the following files in `Assets > Plugins > Android`:

    * `mainTemplate.gradle`
    * `gradleTemplate.properties`

    <img src="https://mintcdn.com/brightdata-31a14106/a71ZLdHh7QHMg9mg/integration-guides/image/unity_integration_guide_2.png?fit=max&auto=format&n=a71ZLdHh7QHMg9mg&q=85&s=581e5cb9aa9bddd080be594589587df6" alt="Enable Custom Gradle Templates" width="400" data-path="integration-guides/image/unity_integration_guide_2.png" />
  </Step>

  <Step title="Update Dependencies in mainTemplate" titleSize="h3">
    Add the following dependencies to the `dependencies` section of `mainTemplate.gradle`:

    ```groovy theme={null}
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.aar'])
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'androidx.core:core:1.9.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
        implementation 'androidx.multidex:multidex:2.0.1'
    }
    ```
  </Step>

  <Step title="Update gradleTemplate" titleSize="h3">
    Add the following to `gradleTemplate.properties`:

    ```properties theme={null}
    android.useAndroidX=true
    android.enableJetifier=true
    ```
  </Step>

  <Step title="Implement ChoiceListener Interface" titleSize="h3">
    Create a `ChoiceListener` class to handle the user's consent choice callback:

    ```csharp theme={null}
    class ChoiceListener : AndroidJavaProxy
    {
        public ChoiceListener() : base("com.android.eapx.Settings$OnStatusChange") { }

        void onChange(int choice)
        {
            // Callback with the user's choice:
            // 1 - user agreed
            // 4 - user declined
        }
    }
    ```
  </Step>

  <Step title="Instantiate Necessary Objects" titleSize="h3">
    ```csharp theme={null}
    AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

    // Important when testing: currentActivity is only available on a device/emulator,
    // not inside the Unity Editor
    AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");

    // Use the full package name - update if you have a dedicated package name
    AndroidJavaObject brightApi = new AndroidJavaObject("com.android.eapx.BrightApi");

    // Create a settings object
    AndroidJavaObject settings = new AndroidJavaObject("com.android.eapx.Settings", currentActivity);
    ```
  </Step>

  <Step title="Set the Behavior of the SDK" titleSize="h3">
    ```csharp theme={null}
    // Refer to the API documentation for all available settings

    // Benefit text appears at the start of the consent text
    settings.Call("setBenefit", "To get free daily tokens");

    // Set button texts (defaults will be used if not set)
    settings.Call("setAgreeBtn", "Yes, sure!");
    settings.Call("setDisagreeBtn", "No, thanks!");

    // Prevent the consent screen from showing automatically
    settings.Call("setSkipConsent", true);

    // Register the ChoiceListener callback
    ChoiceListener choiceListener = new ChoiceListener();
    settings.Call("setOnStatusChange", choiceListener);
    ```
  </Step>

  <Step title="Consent Dialog Customization (optional)" titleSize="h3">
    While the standard Bright SDK consent screen is always available, we **highly encourage customization** to match your app's look & feel - this typically leads to higher conversion rates.

    There are two customization options:

    | Option                  | Description                                   |
    | :---------------------- | :-------------------------------------------- |
    | `CustomConsentSettings` | Modify the built-in Bright SDK consent screen |
    | External consent screen | Build your own consent UI entirely            |

    <AccordionGroup>
      <Accordion title="Option 1 - External Consent Screen">
        <CustomConsent platform="unity" />
      </Accordion>

      <Accordion title="Option 2 - CustomConsentSettings">
        Use `CustomConsentSettings` to customize colors, fonts, backgrounds, and button styles:

        ```csharp theme={null}
        AndroidJavaObject customConsentSettings = new AndroidJavaObject("com.android.eapx.CustomConsentSettings");

        // Colors
        customConsentSettings.Call("setConsentTextColor", "#FFFFFF");
        customConsentSettings.Call("setAgreeButtonBackgroundColor", "#d0510c");
        customConsentSettings.Call("setDisagreeButtonTextColor", "#FFFFFF");
        customConsentSettings.Call("setConsentTextLinksColor", "#FFFFFF");
        customConsentSettings.Call("setAppTitleTextColor", "#facd00");
        customConsentSettings.Call("setHideNetworkIcons", true);
        customConsentSettings.Call("setPrivacyMessageLinksColor", "#facd00");
        customConsentSettings.Call("setPrivacyMessageTextColor", "#ffffff");

        // Font — using system font family and style
        AndroidJavaClass consentFont = new AndroidJavaClass("com.android.eapx.CustomConsentSettings$CustomFontFamily");
        AndroidJavaObject consentFontEnumValue = consentFont.GetStatic<AndroidJavaObject>("monospace");

        AndroidJavaClass consentFontStyle = new AndroidJavaClass("com.android.eapx.CustomConsentSettings$CustomTextStyle");
        AndroidJavaObject consentFontStyleEnumValue = consentFontStyle.GetStatic<AndroidJavaObject>("italic");

        AndroidJavaObject customTypeface = new AndroidJavaObject("com.android.eapx.CustomTypeface");
        customTypeface.Call("setFontFamily", consentFontEnumValue);
        customTypeface.Call("setTextStyle", consentFontStyleEnumValue);
        customConsentSettings.Call("setCustomTypeface", customTypeface);

        // Apply customConsentSettings to the SDK settings
        settings.Call("setCustomConsentSettings", customConsentSettings);
        ```

        📖 See the full list of available `CustomConsentSettings` properties in the [API Documentation](#api-documentation).

        <AccordionGroup>
          <Accordion title="Custom Images">
            To use custom images in the consent screen, copy them to the `StreamingAssets` folder of the app.

            <Info>
              On Android, images in `StreamingAssets` are not directly accessible - they must be loaded via a local web request.
            </Info>

            The following example loads custom images for the consent icon, background, and buttons:

            ```csharp theme={null}
            public static string CUSTOM_CONSENT_BACKGROUND_IMAGE      = "background_image";
            public static string CUSTOM_CONSENT_ICON_IMAGE            = "icon_image";
            public static string CUSTOM_CONSENT_AGREE_BUTTON_IMAGE    = "agree_button_image";
            public static string CUSTOM_CONSENT_DISAGREE_BUTTON_IMAGE = "disagree_button_image";

            void setCustomConsent()
            {
                customConsentSettings = new AndroidJavaObject("com.android.eapx.CustomConsentSettings");
                Dictionary<string, StreamingAsset> imagesDictionary = createImagesDictionary();
                settings.Call("setCustomConsentSettings", customConsentSettings);
                StartCoroutine(LoadFiles(imagesDictionary));
            }

            Dictionary<string, StreamingAsset> createImagesDictionary()
            {
                string backgroundImagePath     = System.IO.Path.Combine(Application.streamingAssetsPath, "your_background_image.png");
                string iconImagePath           = System.IO.Path.Combine(Application.streamingAssetsPath, "your_icon.jpg");
                string agreeButtonImagePath    = System.IO.Path.Combine(Application.streamingAssetsPath, "agree_button.png");
                string disagreeButtonImagePath = System.IO.Path.Combine(Application.streamingAssetsPath, "disagree_button.png");

                Dictionary<string, StreamingAsset> imagesDictionary = new Dictionary<string, StreamingAsset>();
                imagesDictionary.Add(CUSTOM_CONSENT_ICON_IMAGE,             new StreamingAsset(iconImagePath, null));
                imagesDictionary.Add(CUSTOM_CONSENT_BACKGROUND_IMAGE,       new StreamingAsset(backgroundImagePath, null));
                imagesDictionary.Add(CUSTOM_CONSENT_AGREE_BUTTON_IMAGE,     new StreamingAsset(agreeButtonImagePath, null));
                imagesDictionary.Add(CUSTOM_CONSENT_DISAGREE_BUTTON_IMAGE,  new StreamingAsset(disagreeButtonImagePath, null));
                return imagesDictionary;
            }

            IEnumerator LoadFiles(Dictionary<string, StreamingAsset> imagesDictionary)
            {
                List<StreamingAsset> imagesList = new List<StreamingAsset>(imagesDictionary.Values);
                StreamingAsset streamingAsset;

                for (int i = 0; i < imagesList.Count; i++)
                {
                    streamingAsset = imagesList[i];
                    WWW www = new(streamingAsset.Url);
                    yield return www;
                    streamingAsset.ImageBytes = www.bytes;
                }
                updateConsentImages(imagesDictionary);
                brightApi.CallStatic("init", currentActivity, settings);
            }

            private void updateConsentImages(Dictionary<string, StreamingAsset> imagesDictionary)
            {
                customConsentSettings.Call("setBodyBackgroundImageBytes",
                    imagesDictionary[CUSTOM_CONSENT_BACKGROUND_IMAGE].ImageBytes);
                customConsentSettings.Call("setAgreeButtonImageBytes",
                    imagesDictionary[CUSTOM_CONSENT_AGREE_BUTTON_IMAGE].ImageBytes);
                customConsentSettings.Call("setDisagreeButtonImageBytes",
                    imagesDictionary[CUSTOM_CONSENT_DISAGREE_BUTTON_IMAGE].ImageBytes);
                settings.Call("setShowAppIcon", true,
                    imagesDictionary[CUSTOM_CONSENT_ICON_IMAGE].ImageBytes);
            }

            public class StreamingAsset
            {
                public StreamingAsset(string url, byte[] imageBytes)
                {
                    this.Url = url;
                    this.ImageBytes = imageBytes;
                }
                public string Url;
                public byte[] ImageBytes;
            }
            ```
          </Accordion>

          <Accordion title="Unity Editor Customization Example">
            The following is a complete end-to-end example of setting up the custom consent screen using Unity's editor-exposed fields, which is the recommended approach for designer-friendly customization.

            <img src="https://mintcdn.com/brightdata-31a14106/a71ZLdHh7QHMg9mg/integration-guides/image/unity_integration_guide_3.jpg?fit=max&auto=format&n=a71ZLdHh7QHMg9mg&q=85&s=00ddb94ea7e10f1bb650643d57026ce8" alt="Unity Custom Consent In-Game" width="600" data-path="integration-guides/image/unity_integration_guide_3.jpg" />

            **Step 1 - Define variables in your initializer script**

            In the script that initializes Bright Data, define variables for images, button images, icon, and text colors:

            ```csharp theme={null}
            // Exposed Sprite references — editable in the Unity Editor
            [SerializeField] private Sprite _backgroundImage;
            [SerializeField] private Sprite _buttonImage;
            [SerializeField] private Sprite _iconImage;

            // Exposed Colors — editable in the Unity Editor
            [SerializeField] private Color _descriptionTextColor = Color.white;
            [SerializeField] private Color _linksColor           = Color.white;
            [SerializeField] private Color _titleColor           = Color.white;
            [SerializeField] private Color _footerTextColor      = Color.white;
            [SerializeField] private Color _footerLinksColor     = Color.white;

            // Internal variables — store images and colors in Bright SDK-compatible formats
            private byte[] _backgroundImageBytes;
            private byte[] _buttonImageBytes;
            private byte[] _iconImageBytes;
            private string _descriptionTextHex;
            private string _linksHex;
            private string _titleHex;
            private string _footerTextHex;
            private string _footerLinksHex;
            ```

            <img src="https://mintcdn.com/brightdata-31a14106/a71ZLdHh7QHMg9mg/integration-guides/image/unity_integration_guide_4.png?fit=max&auto=format&n=a71ZLdHh7QHMg9mg&q=85&s=946ca6deab0571326cdaa0d0e6f58ae2" alt="Unity Inspector Variables" width="400" data-path="integration-guides/image/unity_integration_guide_4.png" />

            <Warning>
              **Important:** Images must have "**Read/Write**" enabled in their Unity import settings, otherwise they cannot be converted to byte arrays.
            </Warning>

            <img src="https://mintcdn.com/brightdata-31a14106/a71ZLdHh7QHMg9mg/integration-guides/image/unity_integration_guide_5.png?fit=max&auto=format&n=a71ZLdHh7QHMg9mg&q=85&s=7b5bb92c9fa4ccc063cf2c710065cca5" alt="Texture Import Settings Read/Write" width="400" data-path="integration-guides/image/unity_integration_guide_5.png" />

            **Step 2 - Convert images and colors in `Awake()`**

            In the `Awake()` function, convert Sprites and Colors to the formats required by Bright SDK:

            ```csharp theme={null}
            private void Awake()
            {
                // Convert Sprites to PNG byte arrays
                if (_backgroundImage) _backgroundImageBytes = _backgroundImage.texture.EncodeToPNG();
                if (_buttonImage)     _buttonImageBytes     = _buttonImage.texture.EncodeToPNG();
                if (_iconImage)       _iconImageBytes       = _iconImage.texture.EncodeToPNG();

                // Convert Colors to hex strings
                _descriptionTextHex = "#" + ColorUtility.ToHtmlStringRGB(_descriptionTextColor);
                _linksHex           = "#" + ColorUtility.ToHtmlStringRGB(_linksColor);
                _titleHex           = "#" + ColorUtility.ToHtmlStringRGB(_titleColor);
                _footerTextHex      = "#" + ColorUtility.ToHtmlStringRGB(_footerTextColor);
                _footerLinksHex     = "#" + ColorUtility.ToHtmlStringRGB(_footerLinksColor);
            }
            ```

            **Step 3 - Apply custom consent settings before `init()`**

            Before calling `brightApi.CallStatic("init", ...)`, configure and apply the `CustomConsentSettings`:

            ```csharp theme={null}
            AndroidJavaObject customConsentSettings = new AndroidJavaObject("com.android.eapx.CustomConsentSettings");

            // Text colors
            customConsentSettings.Call("setAppTitleTextColor",         _titleHex);
            customConsentSettings.Call("setConsentTextColor",          _descriptionTextHex);
            customConsentSettings.Call("setConsentTextLinksColor",     _linksHex);
            customConsentSettings.Call("setPrivacyMessageTextColor",   _footerTextHex);
            customConsentSettings.Call("setPrivacyMessageLinksColor",  _footerLinksHex);

            // Button colors
            customConsentSettings.Call("setAgreeButtonBackgroundColor",  "#5b13a8");
            customConsentSettings.Call("setDisagreeButtonTextColor",     "#3D7FFC");

            // Hide network icons
            customConsentSettings.Call("setHideNetworkIcons", true);

            // Images (only set if available)
            if (_backgroundImageBytes != null)
                customConsentSettings.Call("setBodyBackgroundImageBytes", _backgroundImageBytes);
            if (_buttonImageBytes != null)
                customConsentSettings.Call("setAgreeButtonImageBytes", _buttonImageBytes);
            if (_buttonImageBytes != null)
                customConsentSettings.Call("setDisagreeButtonImageBytes", _buttonImageBytes);

            // App icon
            if (_iconImageBytes != null)
                settings.Call("setShowAppIcon", true, _iconImageBytes);

            // Apply to SDK settings
            settings.Call("setCustomConsentSettings", customConsentSettings);
            ```
          </Accordion>
        </AccordionGroup>
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Initialize the SDK" titleSize="h3">
    ```csharp theme={null}
    brightApi.CallStatic("init", currentActivity, settings);
    ```
  </Step>

  <Step title="Show the Consent Screen" titleSize="h3">
    ```csharp theme={null}
    // Show consent screen with current settings:
    brightApi.CallStatic("showConsent", currentActivity);

    // If you need to update settings after init, pass the updated settings object:
    brightApi.CallStatic("showConsent", currentActivity, settings);
    ```
  </Step>

  <Step title="Add Opt-In/Out Settings Option" titleSize="h3">
    <Warning>
      Read and implement this section carefully. The user must always be able to opt out of Bright SDK after giving their initial consent.
    </Warning>

    Your app must include a settings option allowing users to opt in or out at any time. This is typically placed in a **Settings** menu.

    <Note>
      Every time the user toggles Web Indexing **ON**, the consent screen must reappear — regardless of any previous opt-in.
    </Note>

    **<u>Mobile Apps</u>**

    **Requirements:**

    * Add a toggle/switch labeled **"Web Indexing"** that clearly reflects the current status (opted in or out)
    * Below the switch, add text emphasizing the value users receive when opting in
    * Include a **"Learn more"** link that opens: [https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing](https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing)

    <Columns cols={2}>
      <img src="https://mintcdn.com/brightdata-31a14106/2IH3hT1mXsDWlTYC/snippets/image/add-opt-in-out-unity-1.png?fit=max&auto=format&n=2IH3hT1mXsDWlTYC&q=85&s=2e77ef03d472f51e2c4d0f928319877f" alt="Alt text" width="400" data-path="snippets/image/add-opt-in-out-unity-1.png" />

      <img src="https://mintcdn.com/brightdata-31a14106/2IH3hT1mXsDWlTYC/snippets/image/add-opt-in-out-unity-2.png?fit=max&auto=format&n=2IH3hT1mXsDWlTYC&q=85&s=d78fc77695ec7e66c25e19698a1c0485" alt="Alt text" width="400" data-path="snippets/image/add-opt-in-out-unity-2.png" />
    </Columns>

    **Implementation:**

    When the user toggles **off**:

    ```csharp theme={null}
    void UserRequestedToTurnOffBrightSdkFromOptions()
    {
        // Disable Bright SDK
        brightApi.CallStatic("optOut", currentActivity);
    }
    ```

    When the user toggles **on** → call `brightApi.CallStatic("showConsent", currentActivity)` to show the consent screen.

    <Note>
      There is no way to directly opt in. Only the user can decide. You must show the consent screen - opt-in happens automatically only if the user agrees.
    </Note>

    **<u>TV Apps</u>**

    **Requirements:**

    * Add a toggle/switch labeled **"Web Indexing"** that clearly reflects the current status
    * Below the switch, add text emphasizing the value users receive when opting in
    * Include a **QR code** linking to: [https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing](https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing)
      * Must be accompanied by: *"Scan the QR Code to learn more."*
      * You may use your own branded QR code, or the hosted [version provided](#)

    <img src="https://mintcdn.com/brightdata-31a14106/2IH3hT1mXsDWlTYC/snippets/image/add-opt-in-out-unity-3.png?fit=max&auto=format&n=2IH3hT1mXsDWlTYC&q=85&s=1e71a8b0b316c126e4762646a1376659" alt="Alt text" width="400" data-path="snippets/image/add-opt-in-out-unity-3.png" />

    <Check>
      You may add a confirmation dialog to discourage opting out (e.g., "If you disable Web Indexing, you will start seeing ads. Continue?")
    </Check>

    <Columns cols={2}>
      <img src="https://mintcdn.com/brightdata-31a14106/2IH3hT1mXsDWlTYC/snippets/image/add-opt-in-out-unity-4.png?fit=max&auto=format&n=2IH3hT1mXsDWlTYC&q=85&s=2e5eb18c088bb0bd90648fca89287f69" alt="Alt text" width="400" data-path="snippets/image/add-opt-in-out-unity-4.png" />

      <img src="https://mintcdn.com/brightdata-31a14106/2IH3hT1mXsDWlTYC/snippets/image/add-opt-in-out-unity-5.png?fit=max&auto=format&n=2IH3hT1mXsDWlTYC&q=85&s=9d45510daeb24bce4d3fd37137f7d76c" alt="Alt text" width="400" data-path="snippets/image/add-opt-in-out-unity-5.png" />
    </Columns>

    **Value text suggestions (both mobile and TV):**

    | State     | Example text                           |
    | --------- | -------------------------------------- |
    | Opted out | "Enable to see fewer ads"              |
    | Opted out | "Enable to get 100 extra coins"        |
    | Opted out | "Enable to enjoy premium features"     |
    | Opted in  | "When enabled you see fewer ads"       |
    | Opted in  | "When enabled you get 100 extra coins" |

    Refrain from using technical terms like "opt in" / "opt out" — always speak in terms of user value.

    **Opt-Out Messages (Optional but highly recommended):**

    | Example | Comments                                                            |
    | ------- | ------------------------------------------------------------------- |
    | Bad     | Avoid using technical terms "opt in" / "opt out"                    |
    | Bad     | Default choice should be the green checkmark (Web Indexing enabled) |
    | Good    | Dialog box discouraging opt-out, reminding user of value they lose  |
    | Good    | Correct messaging, correct default choice                           |
    | Good    | Dialog box validating user's choice, reminding how to opt back in   |
  </Step>

  <Step title="External Consent Screen (optional)" titleSize="h3">
    <CustomConsent platform="unity" />
  </Step>

  <Step title="How to Update the SDK" titleSize="h3">
    <AccordionGroup>
      <Accordion title={<span>Option A - Using the Unity Plugin <Badge color="green" size="md">Recommended</Badge></span>}>
        The [Bright SDK Unity Plugin](https://github.com/BrightSDK/unity-plugin) handles updates automatically. As long as the version in `Assets/Editor/BrightSDK/BrightSDK.json` is set to `null` (latest), the plugin will fetch and replace the SDK on every build. No manual file replacement needed.

        To trigger an update manually, simply build your project again:

        1. Open **File → Build Settings**
        2. Click **Build** or **Build and Run**
      </Accordion>

      <Accordion title="Option B - Manual">
        1. Delete `bright_sdk.aar` from `Assets > Plugins > Android`
        2. Copy the new `bright_sdk.aar` into `Assets > Plugins > Android`
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Migrating from API V1 to V2" titleSize="h3">
    The V2 API introduces new capabilities and a customizable consent screen. All main V1 methods are deprecated and replaced by `BrightApi` methods.

    **Instantiate `BrightApi` (V1 → V2):**

    ```csharp theme={null}
    // V1:
    AndroidJavaObject brightApi = new AndroidJavaObject("com.android.eapx.main");

    // V2:
    AndroidJavaObject brightApi = new AndroidJavaObject("com.android.eapx.BrightApi");
    ```

    **Initialize with Settings object:**

    ```csharp theme={null}
    // Instantiate a Settings object
    AndroidJavaObject settings = new AndroidJavaObject("com.android.eapx.Settings", currentActivity);

    // Initialize the SDK (must be called after all settings are configured)
    brightApi.CallStatic("init", currentActivity, settings);
    ```

    <Tip>
      The consent screen will be displayed automatically after `init`, unless you explicitly call `settings.Call("setSkipConsent", true)`.
    </Tip>

    **Show the consent screen manually:**

    ```csharp theme={null}
    brightApi.CallStatic("showConsent", currentActivity);
    ```
  </Step>

  <Step title="API Documentation" titleSize="h3">
    <Steps>
      <Step title="BrightApi">
        **Public Methods:**

        | Method                                                          | Description                                                                                                                         |
        | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
        | `static void init(Context context, Settings settings)`          | Initializes the SDK. Call **once** in your first activity. Shows consent dialog automatically unless `setSkipConsent(true)` is set. |
        | `static void showConsent(Activity activity)`                    | Displays the consent dialog. Use when a user tries to close an ad or re-enables Bright SDK from Settings.                           |
        | `static void showConsent(Activity activity, Settings settings)` | Displays the consent dialog with a new settings object.                                                                             |
        | `static void optOut(Context context)`                           | Revokes the user's consent and sets `Choice.NOT_PEER`. Triggers `OnStatusChange` callback.                                          |
        | `static Boolean getConsentChoice(Context context)`              | Returns `true` if user is peer, `false` if not peer, `null` if no choice has been made yet.                                         |
        | `static boolean isSvcProcess()`                                 | Returns `true` if the current process is the SDK service process.                                                                   |
        | `static void setTrackingId(String trackingId)`                  | Adds a unique tracking ID for reports and debugging. Must be called **before**`BrightApi.init`.                                     |
        | `static void reportConsentShown(Context context)`               |                                                                                                                                     |
        | `static void reportConsentBackPress(Context context)`           |                                                                                                                                     |
        | `static void reportConsentOptOut(Context context)`              |                                                                                                                                     |
      </Step>

      <Step title="Settings">
        **Constructor:**

        ```java theme={null}
        Settings(Context context)
        ```

        **Public Methods:**

        | Method                                                            | Description                                                             |
        | ----------------------------------------------------------------- | ----------------------------------------------------------------------- |
        | `String getAppId()`                                               | Returns Application ID as defined in `ApplicationInfo.packageName`      |
        | `String getAppName()`                                             | Returns app name as defined in `ApplicationInfo.loadLabel`              |
        | `void setSkipConsent(boolean skipConsent)`                        | Set `true` to prevent consent dialog from showing automatically         |
        | `void setLanguage(ConsentLanguage language)`                      | Override the device default language                                    |
        | `void setBenefit(String benefit)`                                 | Prefix text for the consent dialog (e.g., "To use the app with no ads") |
        | `void setAgreeBtn(String agreeBtn)`                               | Text for the agree button. Default text used if not set.                |
        | `void setDisagreeBtn(String disagreeBtn)`                         | Text for the disagree button. Default text used if not set.             |
        | `void setOnStatusChange(OnStatusChange onStatusChange)`           | Register a callback for user choice changes                             |
        | `void setMinJobId(int minJobId)`                                  | Min job ID for JobScheduler. Default range: 1–1000                      |
        | `void setMaxJobId(int maxJobId)`                                  | Max job ID for JobScheduler. Default range: 1–1000                      |
        | `void setCustomConsentSettings(CustomConsentSettings ccs)`        | Apply custom consent screen settings                                    |
        | `void setShowAppIcon(boolean showAppIcon)`                        | Show the default app icon on the consent screen                         |
        | `void setShowAppIcon(boolean showAppIcon, int appLogoResourceId)` | Show a custom image resource as the app icon                            |
        | `void setShowAppIcon(boolean showAppIcon, byte[] imageBytes)`     | Show a custom image (bytes) as the app icon                             |
        | `void setOptOutInstructions(String optOutInstructions)`           | Custom opt-out instructions text                                        |
        | `void setCampaignId(String campaignId)`                           | Set a campaign ID                                                       |
        | `void setBackPressListener(Runnable backPressListener)`           | Listener for back press on consent screen                               |
      </Step>

      <Step title="CustomConsentSettings">
        | Method                                                      | Description                                                          |
        | ----------------------------------------------------------- | -------------------------------------------------------------------- |
        | `setConsentTitle(String)`                                   | Set the consent screen title                                         |
        | `setAppTitleTextColor(String)`                              | App title text color                                                 |
        | `setAppTitleTypeface(CustomTypeface)`                       | App title font                                                       |
        | `setBodyBackgroundColor(String)`                            | Body background color                                                |
        | `setBodyBackgroundImageResource(int)`                       | Body background image (resource ID)                                  |
        | `setBodyBackgroundImageBytes(byte[])`                       | Body background image (bytes)                                        |
        | `setBodyBackgroundShadow(boolean)`                          | Enable/disable body background shadow                                |
        | `setScreenBackgroundColor(String)`                          | Screen background color                                              |
        | `setScreenBackgroundImageResource(int)`                     | Screen background image (resource ID)                                |
        | `setScreenBackgroundImageResource(int, boolean fillScreen)` | Screen background image with fill option                             |
        | `setScreenBackgroundImageBytes(byte[])`                     | Screen background image (bytes)                                      |
        | `setScreenBackgroundImageBytes(byte[], boolean fillScreen)` | Screen background image (bytes) with fill option                     |
        | `setConsentTextColor(String)`                               | Consent main text color                                              |
        | `setConsentTextTypeface(CustomTypeface)`                    | Consent main text font                                               |
        | `setAgreeButtonImageResource(int)`                          | Agree button image (resource ID)                                     |
        | `setDisagreeButtonImageResource(int)`                       | Disagree button image (resource ID)                                  |
        | `setAgreeButtonImageBytes(byte[])`                          | Agree button image (bytes)                                           |
        | `setDisagreeButtonImageBytes(byte[])`                       | Disagree button image (bytes)                                        |
        | `setAgreeButtonTextColor(String)`                           | Agree button text color                                              |
        | `setDisagreeButtonTextColor(String)`                        | Disagree button text color                                           |
        | `setAgreeButtonTypeface(CustomTypeface)`                    | Agree button font                                                    |
        | `setDisagreeButtonTypeface(CustomTypeface)`                 | Disagree button font                                                 |
        | `setConsentTextLinksColor(String)`                          | Consent text links color                                             |
        | `setAgreeButtonBackgroundColor(String)`                     | Agree button background color                                        |
        | `setDisagreeButtonBackgroundColor(String)`                  | Disagree button background color                                     |
        | `setPrivacyMessageTextColor(String)`                        | Privacy message text color                                           |
        | `setPrivacyMessageLinksColor(String)`                       | Privacy message links color                                          |
        | `setPrivacyMessageTextTypeface(CustomTypeface)`             | Privacy message font                                                 |
        | `setNetworkIconsColorFilter(String)`                        | Network icons color filter                                           |
        | `setNetworkIconsTextColor(String)`                          | Network icons text color                                             |
        | `setNetworkIconsTextTypeface(CustomTypeface)`               | Network icons text font                                              |
        | `setHideNetworkIcons(boolean)`                              | Show/hide network icons                                              |
        | `setQrCodeColorFilter(String)`                              | QR code foreground color                                             |
        | `setQrCodeBackgroundColor(String)`                          | QR code background color                                             |
        | `setCustomTypeface(CustomTypeface)`                         | Apply font to all text elements (specific overrides take precedence) |
        | `setTopIconColorFilter(String)`                             | Top icon color filter                                                |
        | `setHideConsentIcon(boolean)`                               | Show/hide the consent icon                                           |
      </Step>

      <Step title="CustomTypeface">
        **Constructors:**

        ```java theme={null}
        CustomTypeface()
        CustomTypeface(Typeface typeface)
        CustomTypeface(CustomConsentSettings.CustomFontFamily fontFamily,
                       CustomConsentSettings.CustomTextStyle textStyle)
        ```

        **Methods:**

        | Method                                                                  | Description                      |
        | ----------------------------------------------------------------------- | -------------------------------- |
        | `void setTypeface(Typeface typeface)`                                   | Set a `Typeface` object directly |
        | `void setFontFamily(CustomConsentSettings.CustomFontFamily fontFamily)` | Set font family                  |
        | `void setTextStyle(CustomConsentSettings.CustomTextStyle textStyle)`    | Set text style                   |
      </Step>

      <Step title="Choice">
        | Value             | Int | Description                                                |
        | ----------------- | --- | ---------------------------------------------------------- |
        | `Choice.NONE`     | 0   | Consent screen not shown yet, or user hasn't made a choice |
        | `Choice.PEER`     | 1   | User agreed — reflect in settings so user can opt out      |
        | `Choice.NOT_PEER` | 4   | User declined — reflect in settings so user can opt in     |
      </Step>

      <Step title="ConsentLanguage">
        Supported values: `en`, `de`, `es`, `fr`, `it`, `ja`, `pt`, `ru`, `tr`
      </Step>

      <Step title="CustomFontFamily">
        Supported values: `casual`, `cursive`, `monospace`, `sans_serif`, `sans_serif_black`, `sans_serif_light`, `sans_serif_medium`, `sans_serif_smallcaps`, `sans_serif_thin`, `sans_serif_condensed`, `sans_serif_condensed_light`, `sans_serif_condensed_medium`, `serif`, `serif_monospace`
      </Step>

      <Step title="CustomTextStyle">
        Supported values: `bold`, `bold_italic`, `italic`, `normal`
      </Step>
    </Steps>
  </Step>
</Steps>
