This repository contains the official Kotlin OpenFeature provider for Android, to access your feature flags with GO Feature Flag.
In conjuction with the OpenFeature SDK you will be able to evaluate your feature flags in your Android applications.
For documentation related to flags management in GO Feature Flag, refer to the GO Feature Flag documentation website.
- Manage the integration of the OpenFeature Android SDK and GO Feature Flag relay-proxy.
- Prefetch and cache flag evaluations in order to give the flag value in an efficient way.
- Automatic configuration changes polling, to be informed as soon as a flag configuration has changed.
- Automatic data collection about which flags have been accessed by the application
dependencies {
api("dev.openfeature:android-sdk:0.3.0") // check on maven central to get the latest version
implementation("org.gofeatureflag.openfeature:gofeatureflag-kotlin-provider:0.1.0") // check on maven central to get the latest version
}
GO Feature Flag provider needs to be created and then set in the global OpenFeatureAPI.
The only required option to create a GoFeatureFlagProvider
is the URL to your GO Feature Flag relay-proxy instance.
import org.gofeatureflag.openfeature.bean.GoFeatureFlagOptions
import org.gofeatureflag.openfeature.GoFeatureFlagProvider
// ...
val evaluationContext: EvaluationContext = ImmutableContext(
targetingKey = UUID.randomUUID().toString(),
attributes = mapOf( "age" to Value.Integer(22), "email" to Value.String("[email protected]"))
)
OpenFeatureAPI.setProvider(
GoFeatureFlagProvider(
options = GoFeatureFlagOptions( endpoint = "http://localhost:1031")
),
evaluationContext
)
The evaluation context is the way for the client to specify contextual data that GO Feature Flag uses to evaluate the feature flags, it allows defining rules on the flag.
The targetingKey
is mandatory for GO Feature Flag in order to evaluate the feature flag, it could be the id of a user, a session ID or anything you find relevent to use as identifier during the evaluation.
The setProvider()
function is synchronous and returns immediately however, this does not mean that the provider is ready to be used.
An asynchronous network request to the GO Feature Flag backend to fetch all the flags configured for your application must be completed by the provider first. The provider will then emit a READY
event indicating you can start resolving flags.
If you prefer to wait until the fetch is done you can use the suspend
compatible API available for waiting the Provider to become ready:
runBlocking{
OpenFeatureAPI.shared.setProviderAndWait(
provider = provider,
dispatcher = Dispatchers.IO,
initialContext = evaluationContext
)
}
When initializing the provider, you can pass some options to configure the provider and how it behaves with GO Feature Flag.
Option name | Type | Default | Description |
---|---|---|---|
endpoint |
String | endpoint is the URL where your GO Feature Flag server is located. | |
timeout |
Long | 10000 | (optional) timeout is the time in millisecond we wait for an answer from the server. |
maxIdleConnections |
Int | 1000 | (optional) maxIdleConnections is the maximum number of connexions in the connexion pool. |
keepAliveDuration |
Long | 7200000 | (optional) keepAliveDuration is the time in millisecond we keep the connexion open. |
apiKey |
String | (optional) If GO Feature Flag is configured to authenticate the requests, you should provide an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key. | |
pollingIntervalInMillis |
Long | 300000 | (optional) Polling interval in millisecond to check with GO Feature Flag relay proxy if there is a flag configuration change. |
flushIntervalMs |
Long | 1000 | (optional) Time to wait before calling GO Feature Flag to store all the data about the evaluation in the relay proxy. |
During the usage of your application it may appear that the EvaluationContext
should be updated. For example, if a not logged-in user authentify himself, you will probably have to update the evaluation context.
val newContext: EvaluationContext = ImmutableContext(
targetingKey = userId,
attributes = mapOf( "age" to Value.Integer(32), "email" to Value.String("[email protected]"))
)
OpenFeatureAPI.setEvaluationContext(newEvalCtx)
setEvaluationContext()
is a synchronous function similar to setProvider()
and will fetch the new version of the feature flags based on this new EvaluationContext
.
The client is used to retrieve values for the current EvaluationContext
. For example, retrieving a boolean value for the flag "my-flag":
val client = OpenFeatureAPI.getClient()
val result = client.getBooleanValue("my-flag", false)
GO Feature Flag supports different all OpenFeature supported types of feature flags, it means that you can use all the accessor directly
// Bool
client.getBooleanValue("my-flag", false)
// String
client.getStringValue("my-flag", "default")
// Integer
client.getIntegerValue("my-flag", 1)
// Double
client.getDoubleValue("my-flag", 1.1)
// Object
client.getObjectValue("my-flag", Value.structure(mapOf("email" to Value.String("[email protected]"))))
Note
If you add a new flag in GO Feature Flag, expect some delay before having it available for the provider. Refreshing the cache from remote happens when setting a new provider and/or evaluation context in the global OpenFeatureAPI, but also when a configuration change is detected during the polling.
When setting the provider or the context (via setEvaluationContext()
or setProvider()
) some events can be triggered to know the state of the provider.
To listen to them, you can add an event handler via the OpenFeatureAPI
shared instance:
val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
provider.observe<OpenFeatureEvents.ProviderStale>().collect {
providerStaleEventReceived = true
}
}
ProviderReady
: Provider is ready.ProviderError
: Provider in error.ProviderStale
: Provider has not the latest version of the feature flags.ProviderNotReady
: Provider is not ready to evaluate the feature flags.
Status | Feature | Description |
---|---|---|
✅ | Flag evaluation | It is possible to evaluate all the type of flags |
✅ | Cache invalidation | A polling mechanism is in place to refresh the cache in case of configuration change |
❌ | Logging | Not supported by the SDK |
✅ | Flag Metadata | You have access to your flag metadata |
✅ | Event Streaming | You can register to receive some internal event from the provider |
✅ | Unit test | The test are running one by one, but we still have an issue open to enable fully the tests |
Implemented: ✅ | In-progress:
This project welcomes contributions from the community. If you're interested in contributing, see the contributors' guide for some helpful tips.