Skip to content

spotify/confidence-sdk-android

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Maven Central

Confidence SDK for Android

This is the Android SDK for Confidence, a feature flagging and Experimentation system developed by Spotify.

It contains the Confidence OpenFeature Provider, to be used in conjunction with the Open Feature SDK.

For documentation related to flag management and event tracking in Confidence, refer to Confidence decumentation website.

Functionalities:

  • Managed integration with the Confidence backend
  • Prefetch and cache flag evaluations, for fast value reads even when the application is offline
  • Automatic data collection about which flags have been accessed by the application
  • Event tracking for instrumenting your application

Usage

Adding the package dependency

The latest release of the SDK and the Provider is available on Maven central.

Add the following dependency to your gradle file:

implementation("com.spotify.confidence:openfeature-provider-android:0.5.3")

Where 0.5.3 is the most recent version of the Provider. Released versions can be found under "Releases" within this repository.

Creating the Confidence provider and connecting it to the OpenFeature SDK

You can create your ConfidenceProvider instance using the ConfidenceFactory class like this:

val provider = ConfidenceFeatureProvider.create(ConfidenceFactory.create(
    context = app.applicationContext,
    clientSecret = "<MY_SECRET>",
    region = ConfidenceRegion.EUROPE,
    loggingLevel = LoggingLevel.VERBOSE
),  initialisationStrategy = InitialisationStrategy.FetchAndActivate)

Where MY_SECRET is an API key that can be generated in the Confidence UI. The loggingLevel sets the verbosity level for logging to console. This can be useful while testing your integration with the Confidence SDK.

Initialization strategy

initialisationStrategy is a way to decide how Confidence should act when the provider is being set.

  • ActivateAndFetchAsync will make the last fetched flags available immediately and then trigger a background fetch to update the flags for future sessions.
  • FetchAndActivate will fetch the flags from the Confidence backend, stores the result on disk, and make the same data ready for the Application to be consumed. If freshness of flags are the most important aspect for your use case, this is the strategy to go for. However, this will introduce a delay in making flags available to the application.

Examples and expected behavior:

// Fast startup, possibly stale values (or defaults on first run)
val provider = ConfidenceFeatureProvider.create(
    confidence,
    initialisationStrategy = InitialisationStrategy.ActivateAndFetchAsync
)
OpenFeatureAPI.setProviderAndWait(provider)

val client = OpenFeatureAPI.getClient()
val details = client.getStringDetails("myFlag.message", "default")
// On first run with empty cache: returns default with reason=ERROR (provider not ready)
// On subsequent runs with cached data: returns cached value immediately
// If cache context != current context, reason may be STALE
// Guaranteed fresh values, slower startup (waits for network)
val provider = ConfidenceFeatureProvider.create(
    confidence,
    initialisationStrategy = InitialisationStrategy.FetchAndActivate
)
OpenFeatureAPI.setProviderAndWait(provider)

val client = OpenFeatureAPI.getClient()
val details = client.getStringDetails("myFlag.message", "default")
// Returns freshly fetched value; startup includes network time

Notes:

  • Setting a new evaluation context with OpenFeatureAPI.setEvaluationContextAndWait(...) will fetch and activate new values before returning.
  • With ActivateAndFetchAsync, the background fetch stores new flags to disk but does not swap in-memory values during the session unless a subsequent activation occurs (for example when the context changes via setEvaluationContextAndWait).

Setting the context

The evaluation context is a key-value map that will be used for sampling and for targeting input in assigning feature flag values by the Confidence backend. It is also a crucial way to create dimensions for metrics generated by event data.

To set an evaluation context, you should use the setEvaluationContextAndWait method on the OpenFeature SDK.

val userId: String = "..." // get the user id from your app
val evaluationContext = ImmutableContext(
    targetingKey = userId,
    attributes = mapOf(
    "user_id" to Value.String(userId),
    "country" to Value.String("SE"),
    "product" to Value.String("productId123")
))
OpenFeatureAPI.setEvaluationContextAndWait(evaluationContext)

Note

When you set a new evaluation context, the Confidence provider will automatically pick it up, fetch new flag values and use them for all subsequent flag evaluations.

Resolving flags

Once the flags are fetched and activated, you can access their value using the different methods on the OpenFeature Client.

The get<Type>Value method returns a value of the specified type, where <Type> or the default value specified.

The get<Type>Details method returns a typed FlagEvaluationDetails object that contains the value of the flag, the reason for the value returned, and the variant selected. In the case of an error, the default value will be returned and the errorCode and errorMessage contain information about the error.

The method get<Type>Value will simply return the assigned value or the default.

val client = OpenFeatureAPI.getClient()

val message: String = client.getStringValue("flag-name.message", "default message")
val messageFlag: FlagEvaluationDetails<String> = client.getStringDetails("flag-name.message", "default message")

val messageValue = messageFlag.value
// message and messageValue are the same

Important

You should note that all feature flags in Confidence are complex objects implemented by the ConfidenceValue.Struct class but fear not! You can use a dot-notation to access properties within your flag object for ease of use. Above we show how to access a string property from a flag. In that example the actual flag object is called flag-name and we access the string property message using the dot notation: flag-name.message.

Using the Confidence Standalone SDK

If you want to use the Confidence SDK standalone, you can.

Adding the package dependency

Add the following dependency to your gradle file to use it:

implementation("com.spotify.confidence:confidence-sdk-android:0.5.3")

Where 0.5.3 is the most recent version of this SDK.

Released versions can be found under "Releases" within this repository.

Creating the Confidence instance

You can create your Confidence instance using the ConfidenceFactory class like this:

val confidence = ConfidenceFactory.create(
    context = app.applicationContext,
    clientSecret = "<MY_SECRET>",
    region = ConfidenceRegion.EUROPE,
    loggingLevel = LoggingLevel.VERBOSE
)

Where MY_SECRET is an API key that can be generated in the Confidence UI. The loggingLevel sets the verbosity level for logging to console. This can be useful while testing your integration with the Confidence SDK.

Note: the Confidence SDK has been intended to work as a single instance in your Application. Creating multiple instances in the same runtime could lead to unexpected behaviours.

Initialization strategy

confidence.fetchAndActivate() is an async function that fetches the flags from the Confidence backend, stores the result on disk, and make the same data ready for the Application to be consumed.

The alternative option is to call confidence.activate(): this loads previously fetched flags data from storage and makes that available for the Application to consume right away. To avoid waiting on backend calls when the Application starts, the suggested approach is to call confidence.activate() and then trigger a background refresh via confidence.asyncFetch() for future sessions.

Examples and expected behavior:

// Fast startup, possibly stale values (or defaults on first run)
confidence.activate()
confidence.asyncFetch() // background refresh writes to disk only

val value = confidence.getValue("myFlag.message", "default")
// First run with empty cache: returns default, reason=ERROR (provider not ready)
// Warm start with cache: returns cached value immediately; reason may be STALE if context changed
// Guaranteed fresh values, waits for network before proceeding
await confidence.fetchAndActivate()

val value = confidence.getValue("myFlag.message", "default")
// Returns freshly fetched value

Context updates:

// Fetch and activate after context change, and wait until ready
await confidence.awaitPutContext(mapOf(
    "targeting_key" to ConfidenceValue.String("user-123"),
    "country" to ConfidenceValue.String("SE")
))

val fresh = confidence.getValue("myFlag.message", "default")

Setting the context

The context is a key-value map that will be used for sampling and for targeting input in assigning feature flag values by the Confidence backend. It is also a crucial way to create dimensions for metrics generated by event data.

The Confidence SDK supports multiple ways to set the Context. Some of them are mutating the current context of the Confidence instance, others are returning a new instance with the context changes applied.

confidence.putContext("key", ConfidenceValue.String("value")) // this will mutate the context of the current Confidence instance

val otherConfidenceInstance = confidence.withContext("key", ConfidenceValue.String("value")) // this will return a new Confidence instance with the context changes applied but the context of the original instance is kept intact

Resolving flags

Once the flags are fetched and activated, you can access their value using the getValue method or the getFlag method. Both methods uses generics to return a type defined by the default value type.

The method getFlag returns an Evaluation object that contains the value of the flag, the reason for the value returned, and the variant selected.

In the case of an error, the default value will be returned and the Evaluation contains information about the error.

The method getValue will simply return the assigned value or the default.

val message: String = confidence.getValue("flag-name.message", "default message")
val messageFlag: Evaluation<String> = confidence.getFlag("flag-name.message", "default message")

val messageValue = messageFlag.value
// message and messageValue are the same

Logging

By default, the Confidence SDK will log errors and warnings. You can change the preferred log level by passing a loggingLevel to the Confidence.create() function.

To turn off logging completely, you can pass LoggingLevel.NONE to the Confidence.create() function.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 6

Languages