For the complete documentation index, see llms.txt. This page is also available as Markdown.

Flutter plugin

Add feature flags and experimentation to your cross-platform mobile apps with the Harness FME Flutter plugin.

This guide provides detailed information about our Flutter plugin which is built on top of our Android, iOS and Browser SDKs. The plugin provides you a way to interact with the native SDKs.

All of our SDKs are open source. Go to our Flutter GitHub repository to see the source code.

Before you begin

This plugin supports Android, iOS, and Web platforms.

  • For Android and iOS, Dart SDK v2.16.2 or later and Flutter v2.5.0 or later are required.

  • For Web, Dart SDK v3.3.0 or later and Flutter v3.19.0 or later are required. The package is compatible with WebAssembly (WASM) compilation.

RULE-BASED SEGMENTS SUPPORT

Rule-based segments are supported in plugin versions 1.0.0 and above. No changes are required to your implementation, but updating to a supported version is required to ensure compatibility.

Older SDK versions will return the control treatment for flags using rule-based segments and log an impression with a special label for unsupported targeting rules.

Initialization

Set up Harness FME in your code base with the following steps:

1. Add the package in your pubspec.yaml file

dependencies:
  splitio: 1.2.1

2. Instantiate the plugin

/// Initialize Split plugin
import 'package:splitio/split_client.dart';
import 'package:splitio/splitio.dart';
/// KEY represents your internal user id, or the account id that 
/// the user belongs to. 
/// This could also be a cookie you generate for anonymous users.
final Splitio _split = Splitio('YOUR_SDK_KEY', 'KEY');

We recommend instantiating the Splitio object once as a singleton and reusing it throughout your application.

Configure the plugin with the SDK key for the FME environment that you would like to access. In legacy Split (app.split.io) the SDK key is found on your Admin settings page, in the API keys section. Select a client-side SDK API key. This is a special type of API token with limited privileges for use in browsers or mobile clients. See API keys to learn more.

Using the plugin

Basic use

When the SDK is instantiated, it starts background tasks to update an in-memory cache with small amounts of data fetched from Harness servers. This process can take up to a few hundred milliseconds, depending on the size of data. If the SDK is asked to evaluate which treatment to show to a customer for a specific feature flag while it's in this intermediate state, it may not have the data necessary to run the evaluation. In this case, the SDK does not fail, rather, it returns the control treatment.

To make sure the SDK is properly loaded before asking it for a treatment, wait until the SDK is ready, as shown below. You can use the onReady parameter when creating the client to get notified when this happens.

After the observable calls back, you can use the getTreatment method to return the proper treatment based on the FEATURE_FLAG_NAME and the key variable you passed when instantiating the SDK. Then use an if-else-if block as shown below and insert the code for the different treatments that you defined in Harness FME. Remember the final else branch in your code to handle the client returning control.

Attribute syntax

To target based on custom attributes, pass the client's getTreatment method as an attribute map at runtime.

In the example below, we are rolling out a feature flag to users. The provided attributes plan_type, registered_date, permissions, and deal_size are passed to the getTreatment call. These attributes are compared and evaluated against the attributes used in the rollout plan as defined in Harness FME to decide whether to show the on or off treatment to this account. The getTreatment method supports five types of attributes: strings, numbers, dates, booleans, and sets. The proper data type and syntax for each are:

  • Strings: Use type String.

  • Numbers: Use type num (int or double).

  • Dates: Express the value in milliseconds since epoch. Note: Milliseconds since epoch is expressed in UTC. If your date or date-time combination is in a different timezone, first convert it to UTC, then transform it to milliseconds since epoch.

  • Booleans: Use type bool.

  • Sets: Use type List or Set.

Binding attributes to the client

Attributes can optionally be bound to the client at any time during the SDK lifecycle. These attributes are stored in memory and used in every evaluation to avoid the need to keep the attribute set accessible through the whole app. When an evaluation is called, the attributes provided (if any) at evaluation time are combined with the ones that are already loaded into the SDK memory, with the ones provided at function execution time taking precedence. This enables those attributes to be overridden or hidden for specific evaluations.

An attribute is considered valid if it follows one of the types listed below:

  • String

  • Number

  • Boolean

  • Array

The SDK validates these before storing them and if there are invalid or missing values, possibly indicating an issue, the methods return the boolean false and do not update any value.

To use these methods, refer to the example below:

Multiple evaluations at once

In some instances, you may want to evaluate treatments for multiple feature flags at once. Use the different variations of getTreatments from the SDK factory client to do this.

  • getTreatments: Pass a list of the feature flag names you want treatments for.

  • getTreatmentsByFlagSet: Evaluate all flags that are part of the provided set name and are cached on the SDK instance.

  • getTreatmentsByFlagSets: Evaluate all flags that are part of the provided set names and are cached on the SDK instance.

Get treatments with configurations

To leverage dynamic configurations with your treatments, use the getTreatmentWithConfig method.

This method returns an object containing the treatment and associated configuration:

The config element is a stringified version of the configuration JSON defined in Harness FME. If there is no configuration defined for a treatment, the SDK returns null for the config parameter.

This method taskes the exact set of arguments as the standard getTreatment method. See below examples on proper usage:

If you need to get multiple evaluations at once, you can also use the getTreatmentsWithConfig methods. These methods take the exact same arguments as the getTreatments methods but return a mapping of feature flag names to SplitResult objects instead of strings. Example usage below.

If a flag cannot be evaluated, the SDK returns the fallback treatment value (default "control" unless overridden globally or per flag). For more information, see Fallback treatments.

Append properties to impressions

Impressions are generated by the SDK each time a getTreatment method is called. These impressions are periodically sent back to Harness servers for feature monitoring and experimentation.

You can append properties to an impression by passing an object of key-value pairs to the getTreatment method. These properties are then included in the impression sent by the SDK and can provide useful context to the impression data.

Three types of properties are supported: strings, numbers, and booleans.

Shutdown

Call the client.destroy() method once you've stopped using the client, as this method gracefully shuts down the SDK by stopping all background threads, clearing caches, closing connections, and flushing the remaining unpublished impressions.

After destroy() is called and finishes, any subsequent invocations to getTreatment/getTreatments or manager methods result in control or empty list, respectively.

Track

Use the track method to record any actions your customers perform. Each action is known as an event and corresponds to an event type. Calling track through one of our SDKs or via the API is the first step to getting experimentation data into Harness FME and allows you to measure the impact of your feature flags on your users' actions and metrics. Learn more about using track events.

In the examples below, you can see that the .track() method can take up to four arguments. The proper data type and syntax for each are:

  • EVENT_TYPE: The event type that this event should correspond to. The expected data type is String. Full requirements on this argument are:

    • Contains 63 characters or fewer.

    • Starts with a letter or number.

    • Contains only letters, numbers, hyphen, underscore, or period.

    • This is the regular expression we use to validate the value: [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}

  • TRAFFIC_TYPE: (Optional) The traffic type of the key in the track call. The expected data type is String. You can only pass values that match the names of traffic types that you have defined Harness FME.

  • VALUE: (Optional) The value is used to create the metric. The expected data type is double.

  • PROPERTIES: (Optional) An object of key value pairs that can be used to filter your metrics. Learn more about event properties. FME currently supports three types of properties: strings, numbers, and booleans.

The track method returns a boolean value of true or false to indicate whether or not the client was able to successfully queue the event to be sent back to Harness servers on the next event post. The service returns false if the current queue size is equal to the config set by eventsQueueSize or if an incorrect input to the track method is provided.

In the case that a bad input is provided, you can read more about our SDK's expected behavior.

Configuration

The SDK has a number of knobs for configuring performance. Each knob is tuned to a reasonable default. However, you can override values when instantiating the Splitio:

The parameters available for configuration are shown below.

Configuration

Description

Default value

Supported platforms

featuresRefreshRate

The SDK polls Harness servers for changes to feature flags at this rate (in seconds).

3600 seconds

All

segmentsRefreshRate

The SDK polls Harness servers for changes to segments at this rate (in seconds).

1800 seconds

All

impressionsRefreshRate

Controls how frequently the impressions cache expires after a write (in seconds). The treatment log captures which customer saw which treatment (on, off, etc.) and is periodically flushed back to Harness servers.

1800 seconds

All

telemetryRefreshRate

The SDK caches diagnostic data that it periodically sends to Harness servers. This configuration controls how frequently this data is sent back to Harness servers (in seconds).

3600 seconds (1 hour)

All

eventsQueueSize

When using .track, the number of events to be kept in memory.

10000

All

eventFlushInterval

When using .track, how often is the events queue flushed to Harness servers.

1800 seconds

All

eventsPerPush

Maximum size of the batch to push events.

2000

Android & iOS

trafficType

When using .track, the default traffic type to be used.

not set

All

impressionsQueueSize

Default queue size for impressions.

30K

All

enableDebug

Enabled verbose mode.

false

All

streamingEnabled

Boolean flag to enable the streaming service as default synchronization mechanism when in foreground. In the event of an issue with streaming, the SDK will fallback to the polling mechanism. If false, the SDK will poll for changes as usual without attempting to use streaming.

true

All

persistentAttributesEnabled

Enables saving attributes on persistent cache which is loaded as part of the SDK_READY_FROM_CACHE flow. All functions that mutate the stored attributes map affect the persistent cache.

false

Android & iOS

impressionListener

Enables impression listener. If true, generated impressions stream in the impressionsStream() method of Splitio.

false

All

syncConfig

Use it to filter specific feature flags to be synced and evaluated by the SDK. It can be created with the SyncConfig.flagSets('sets') method (recommended, flag sets aree available in all tiers) or SyncConfig(names: ["feature-flag-1", "feature-flag-2"]) for individual names. If not set, all flags are downloaded.

not set

All

syncEnabled

Controls the SDK continuous synchronization flags. When true, a running SDK processes the rollout plan updates which is performed in Harness FME (default). When false, it fetches all data upon init, which ensures a consistent experience during a user session and optimizes resources when these updates are not consumed by the app.

true

All

userConsent

User consent status controls the tracking of events and impressions. Possible values are UserConsent.granted, UserConsent.decline, and UserConsent.unknown. See User consent for details.

UserConsent.granted

All

encryptionEnabled

Enables or disables encryption for cached data.

false

Android & iOS

logLevel

Enables logging according to the level specified. Options are SplitLogLevel.none, SplitLogLevel.verbose, SplitLogLevel.debug, SplitLogLevel.info, SplitLogLevel.warning, and SplitLogLevel.error.

SplitLogLevel.none

All

impressionsMode

This configuration defines how impressions (decisioning events) are queued. Supported modes are ImpressionsMode.optimized, ImpressionsMode.none, and ImpressionsMode.debug. In ImpressionsMode.optimized mode, only unique impressions are queued and posted to Harness; this is the recommended mode for experimentation use cases. In ImpressionsMode.none mode, no impression is tracked in Harness FME and only minimum viable data to support usage stats is, so never use this mode if you are experimenting with that instance impressions. Use ImpressionsMode.none when you want to optimize for feature flagging only use cases and reduce impressions network and storage load. In ImpressionsMode.debug mode, ALL impressions are queued and sent to Harness. This is useful for validations. This mode doesn't impact the impression listener which receives all generated impressions locally.

ImpressionsMode.optimized

All

readyTimeout

Maximum amount of time (in seconds) to wait until the onTimeout callback is fired or whenTimeout future is completed. A negative value means no timeout.

10 seconds

All

certificatePinningConfiguration

If set, enables certificate pinning for the given domains. For details, see the Certificate pinning section below.

null

Android & iOS

rolloutCacheConfiguration

Specifies how long rollout data is kept in local storage before expiring.

null

All

fallbackTreatments

Configure fallback treatments for the SDK.

null

All

Manager

Use these methods on Splitio instance to get a list of the feature flags available to the SDK factory client.

The SplitView class referenced above has the following structure:

Listener

FME SDKs send impression data back to Harness servers periodically as a result of evaluating feature flags. To additionally send this information to a location of your choice, use the impressionsStream.

This provides a stream that publishes Impression objects every time one is generated.

The Impression class has the following format.

An impression listener is called asynchronously from the corresponding evaluation, but is almost immediate.

Logging

To enable logging, the logLevel setting is available in the configuration class:

Configure fallback treatments

Fallback treatments let you define a treatment value (and optional configuration) to be returned when a flag cannot be evaluated. By default, the SDK returns control, but you can override this globally or for individual flags at the SDK level.

This is useful when you want to:

  • Maintain a predictable user experience during outages or evaluation failures (avoid unexpected control in production)

  • Protect critical user flows by returning a safe, stable treatment (for example, forcing off during an incident)

  • Customize behavior per flag so each evaluation inherits appropriate safe defaults if something goes wrong

Global fallback treatment

Set a global fallback treatment when initializing the SDK factory. This value is returned whenever any flag cannot be evaluated.

Flag-level fallback treatment

You can also set a fallback treatment per flag when calling getTreatment or getTreatmentWithConfig. This flag-level fallback always takes precedence over the global fallback treatment, so if both are defined, the SDK will return the flag-level value when that flag cannot be evaluated.

For more information, see Fallback treatments.

Advanced use cases

This section describes advanced use cases and features provided by the SDK.

Instantiate multiple SDK clients

FME supports the ability to release based on multiple traffic types. For example, with traffic types, you can release to users in one feature flag and accounts in another. If you are unfamiliar with using multiple traffic types, refer to the Traffic type guide for more information.

Each SDK factory client is tied to one specific customer ID at a time, so if you need to roll out feature flags by different keys, instantiate multiple SDK clients, one for each traffic type. For example, you may want to roll out the feature USER_POLL by users and the feature ACCOUNT_PERMISSIONING by accounts. You can do this with the example below:

NUMBER OF SDK INSTANCES

While the SDK does not put any limitations on the number of instances that can be created, we strongly recommend keeping the number of clients down to one or two.

Subscribe to events

You can subscribe to four different callbacks when creating a client.

  • onReadyFromCache. This event fires once the SDK is ready to evaluate treatments using a locally cached version of your rollout plan from a previous session (which might be stale). If there is data in the cache, this event fires almost immediately, since access to the cache is fast; otherwise, it doesn't fire.

  • onReady. This event fires once the SDK is ready to evaluate treatments using the most up-to-date version of your rollout plan, downloaded from Harness servers.

  • onTimeout. This event fires if there is no cached version of your rollout plan in disk cache, and the SDK could not fully download the data from Harness servers within the time specified by the readyTimeout configuration parameter. This event does not indicate that the SDK initialization was interrupted. The SDK continues downloading the rollout plan and fires the onReady event when finished. This delayed onReady event may happen with slow connections or large rollout plans with many feature flags, segments, or dynamic configurations.

  • onUpdate. This event fires whenever your rollout plan is changed. Listen for this event to refresh your app whenever a feature flag or segment is changed in Harness FME.

You can also receive Futures (or a Stream, for the Update event) by accessing the following methods in the client.

The plugin allows you to disable the tracking of events and impressions until user consent is explicitly granted or declined.

The userConsent configuration parameter lets you set the initial consent status of the SDK, and the Splitio method setUserConsent(enabled: bool) lets you grant (enable) or decline (disable) the dynamic data tracking.

The following are the three possible initial states:

  • UserConsent.granted. The user grants consent for tracking events and impressions. The SDK sends them to the Harness FME servers. This is the default value if the userConsent param is not defined.

  • UserConsent.declined. The user declines consent for tracking events and impressions. The SDK does not send them to the Harness FME servers.

  • UserConsent.unknown. The user neither grants nor declines consent for tracking events and impressions. The SDK tracks them in its internal storage, and eventually either sends them or not if the consent status is updated to 'GRANTED' or 'DECLINED' respectively. The status can be updated at any time with the setUserConsent factory method.

Certificate pinning

The plugin allows you to constrain the certificates that it trusts, by pinning a certificate's SubjectPublicKeyInfo providing the public key as a base64 SHA-256 hash or a base64 SHA-1 hash.

Each pin corresponds to a host. For subdomains, you can optionally use wildcards, where * will match one subdomain (e.g. *.example.com), and ** will match any number of subdomains (e.g **.example.com).

To set the plugin to require pinned certificates for specific hosts, add the CertificatePinningConfiguration object to the configuration, as shown below.

A native SplitFactory instance can be shared with the plugin to save resources when evaluations need to be performed on native platform logic. To do so, do the following:

Android

  1. If not created already, create a subclass of Android's Application, and add its name to the Manifest.

  1. Add the Android SDK dependency to your project's build.gradle file.

  1. Create a property in your subclass of Application to hold your factory instance.

  2. Initialize the factory in the onCreate callback of your Application subclass.

  1. Make the Application subclass implement the SplitFactoryProvider interface, and return the previously created factory in the overridden getSplitFactory() method.

iOS

  1. Add the iOS SDK dependency to your app's Podfile.

  1. Add a property in your AppDelegate class to hold the factory instance. Make sure to import Split.

  1. Initialize the factory just before the GeneratedPluginRegistrant.register(with: self) line.

  1. Implement the SplitFactoryProvider protocol in your AppDelegate and return the previously created factory in the overridden getFactory() method.

Last updated

Was this helpful?