# Flutter

{% hint style="info" %}
Hackle Flutter SDK supports Flutter SDK 2.0.0 and above.

Flutter SDK is built on top of [Android SDK](/en/development-guide/android.md) and [iOS SDK](/en/development-guide/ios.md). The following OS versions are supported.

* Android API 16 (4.1 Jelly Bean) and above
* iOS 13 and above
  {% endhint %}

{% hint style="info" %}
Starting from Hackle Flutter SDK 2.29.0, the minimum supported iOS version has been raised to iOS 13.

For versions below Hackle Flutter SDK 2.29.0, the minimum supported iOS version is iOS 10.
{% endhint %}

## Add SDK Dependency

[![](https://img.shields.io/pub/v/hackle)](https://pub.dev/packages/hackle)

Add the SDK dependency.

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

```bash
flutter pub add hackle
```

{% endtab %}

{% tab title="pubspec.yaml" %}

```yaml
dependencies:
	hackle: ^2.7.0
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
After installing or updating the SDK, you must rebuild the app for the integration changes to take effect.
{% endhint %}

## SDK Initialization

You must initialize `HackleApp` before using the SDK. An SDK Key is required to initialize `HackleApp`.

* `HackleApp` is a class that provides methods for using the SDK features.
* You can find the SDK Key in [SDK Integration Info](https://dashboard.hackle.io/config/sdk-setting) on the Hackle Service Dashboard.

During initialization, the SDK fetches required information from the Hackle server and stores it locally.

Initialization runs asynchronously, and you can use `await` to wait until initialization is complete.

{% hint style="warning" %}
If you call A/B Test or Feature Flag methods before initialization completes, they will return the default group (A) or off (false).
{% endhint %}

```dart
import "package:hackle/hackle.dart";

await HackleApp.initialize(YOUR_APP_SDK_KEY);
```

#### Recommended Initialization Strategy: Initialize via Splash Screen

Instead of launching the app immediately, display a splash screen while the SDK initializes. Once initialization completes, use a callback to close the splash screen and allow users to interact with the app.

### Inject User on Initialization

You can initialize the SDK with user information included.

* If no user information is provided, the SDK uses user information stored in local storage.
* If user information is provided, the SDK does not use information stored in local storage.
* If no user is injected and no user information is stored in local storage, the SDK uses a user with the Hackle Device ID as the device ID.

{% hint style="info" %}
User information can be freely updated after SDK initialization using the user info setter functions.
{% endhint %}

{% hint style="warning" %}
User information injected during initialization is not merged with user information stored in local storage.

ex) If userId: A is stored in storage and you inject deviceId: B during initialization, the user will be set to userId: null, deviceId: B.
{% endhint %}

```dart
import "package:hackle/hackle.dart";

HackleConfig config = HackleConfigBuilder()
  .build();

HackleUser user = HackleUserBuilder()
  .userId("YOUR_USER_ID")
  .build();

await HackleApp.initialize(YOUT_APP_SDK_KEY, hackleConfig: config, user: user);
```

### SDK Initialization Config

You can add several configuration options when initializing the SDK.

```dart
import "package:hackle/hackle.dart";

HackleConfig config = HackleConfigBuilder()
  .build();

await HackleApp.initialize(YOUT_APP_SDK_KEY, hackleConfig: config);
```

<table data-full-width="false"><thead><tr><th width="223.26171875">Config</th><th width="295.48828125">Description</th><th width="125.8125">Default</th><th width="99.55859375">Supported Version</th></tr></thead><tbody><tr><td><code>exposureEventDedupIntervalMillis</code></td><td><p>Removes duplicate exposure events for the same A/B Test or Feature Flag distribution result triggered consecutively by the same user.</p><ul><li>Min value: 1000 (1 second)</li><li>Max value: 3600000 (1 hour)</li></ul></td><td>-1 (no deduplication)</td><td>All versions</td></tr><tr><td><code>debug</code></td><td>Outputs logs for all features to the console and sends events immediately.</td><td><code>false</code></td><td>2.1.0+</td></tr><tr><td><code>pollingIntervalMillis</code></td><td><p>Periodically updates settings configured in the Dashboard.</p><ul><li>Min value: 60000 (60 seconds)</li></ul></td><td>-1 (no periodic update)</td><td>2.3.0+</td></tr><tr><td><code>automaticScreenTracking</code></td><td>Detects Activity / ViewController changes at the Android / iOS level to track screen transitions.</td><td><code>true</code></td><td>2.21.0+</td></tr><tr><td><code>sessionPolicy</code></td><td>Configures session persistence and expiry conditions.</td><td><p><code>ALWAYS_NEW_SESSION</code> ,</p><p><code>1800000</code></p></td><td>2.30.0+</td></tr><tr><td><code>optOutTracking</code></td><td>Whether Opt-out is enabled.</td><td><code>false</code></td><td>2.30.0+</td></tr><tr><td><code>sessionTimeoutMillis</code> (deprecated)</td><td>Sets the session timeout duration. Please use <code>sessionPolicy</code> instead.</td><td>1800000 (30 minutes)</td><td>2.9.0+</td></tr></tbody></table>

#### Session Policy Configuration

You can control session persistence and expiry conditions by configuring the session policy.

```dart
import "package:hackle/hackle.dart";

HackleSessionPolicy sessionPolicy = HackleSessionPolicy.builder()
    .persistCondition(HackleSessionPersistCondition.nullToUserId)
    .timeoutCondition(
        HackleSessionTimeoutCondition.builder()
            .timeoutMillis(3600000)
            .onForeground(false)
            .onBackground(true)
            .onApplicationStateChange(true)
            .build()
    )
    .build();

HackleConfig config = HackleConfigBuilder()
    .sessionPolicy(sessionPolicy)
    .build();

await HackleApp.initialize(YOUR_APP_SDK_KEY, hackleConfig: config);
```

### Refresh Dashboard Config

You can explicitly refresh the Dashboard configuration.

{% hint style="warning" %}
This function can be called at most once every 60 seconds.
{% endhint %}

```dart
HackleApp.fetch();
```


---

# Agent Instructions: 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:

```
GET https://docs.hackle.io/en/development-guide/flutter.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
