SDKs

Flagbearer for Android

The Kotlin SDK for Flagbearer, for Android apps. Requires Android 6.0 (API 23) or later and has no dependencies.

Server-side Kotlin uses the Java SDK instead.

Install

Gradle (Kotlin DSL):

dependencies {
    implementation("dev.flagbearer:flagbearer-android:VERSION")
}

Replace VERSION with the latest release, listed on Maven Central.

Keys

Use a client key, which starts with fbc_. Client keys are public and safe to include in an app. Server keys, which start with fbs_, are secret and belong only on your server.

Set up one client

Create one client for the whole app, in your Application class:

import dev.flagbearer.android.Flagbearer

class App : Application() {
    lateinit var flags: Flagbearer

    override fun onCreate() {
        super.onCreate()
        flags = Flagbearer(this, clientKey = "fbc_...")
    }
}

Flags load in the background and are kept on the device, so the app starts with the flags each user last had, even offline.

While the app is in the foreground, a change you make in the dashboard reaches it within a couple of seconds, over a live connection. If that connection drops, the SDK checks every 30 seconds until it's back. After five minutes in the background it stops both, and catches up when the app returns.

Users

When the signed-in user is known or changes, call identify from a coroutine:

flags.identify(User(key = user.id, email = user.email))

The email is optional. Include it to turn flags on for testers by email. After sign-out, call identify(User()).

Checking a flag

if (flags.isEnabled("new-checkout")) {
    showNewCheckout()
}

isEnabled never waits and never throws. It returns false until the current user's flags have loaded, and when the flag doesn't exist. Pass another default as flags.isEnabled("new-checkout", defaultValue = true).

flags.status is FlagsStatus.LOADING until the current user's flags arrive. Use it to hold back UI that mustn't switch between the default and the real value.

Jetpack Compose

Read a flag as state, so the screen redraws when it changes:

@Composable
fun rememberFlag(flags: Flagbearer, key: String, defaultValue: Boolean = false): Boolean {
    var enabled by remember(key) { mutableStateOf(flags.isEnabled(key, defaultValue)) }
    DisposableEffect(key) {
        val subscription = flags.subscribe { enabled = flags.isEnabled(key, defaultValue) }
        onDispose { subscription.close() }
    }
    return enabled
}
if (rememberFlag(flags, "new-checkout")) NewCheckout() else Checkout()

subscribe calls its listener on the main thread whenever flags or status change. Close what it returns to stop listening.

Error reports

allFlags() returns every flag's current value, so error reports show exactly which flags were on. It doesn't count as checking them.

crashReporter.setContext("flags", flags.allFlags())
// {new-checkout=true, dark-mode=false}

When something is wrong

The SDK never crashes or blocks the app over a flag problem. It keeps the last flags, or defaults, and says what's wrong in Logcat under the Flagbearer tag:

  • A key the server refuses is explained once, with the server's reason.
  • A server key (fbs_) is never sent. The log says to use a client key.
  • In debuggable builds, checking a flag that doesn't exist warns once per flag.

Pass debug = true to also log each fetch, and to get the missing-flag warning in release builds.

Options

val flags = Flagbearer(
    context = this,
    clientKey = "fbc_...",
    user = User(key = "42"), // the user at launch, if already known
    debug = false,
    appVersion = null,       // defaults to the app's versionName
    cacheFlags = true,       // start with the flags this user last had
)