Kotlin / Android
Kotlin-first SDK with coroutine support, thread-safe evaluation, and seamless Android integration. Works on Kotlin/JVM and Android.
dependencies {
implementation("com.toggleai:sdk-kotlin:1.0.0")
}
// For Android projects, also add:
// implementation("com.toggleai:sdk-kotlin-android:1.0.0")The Kotlin / Android SDK operates in close harmony with ToggleAI backend services to deliver first-class mobile performance, zero-overhead evaluations, and asynchronous telemetry reporting:
β‘ Local In-Memory Evaluation
When client.init() is called, the SDK makes a single secure HTTP request to GET /sdk/config to retrieve the configuration rules. Subsequent checks via client.getFlag() or client.getFlagValue() execute instantly in-memory (sub-millisecond latency)βcompletely eliminating network delays from critical user interactions or Jetpack Compose rendering paths.
π°οΈ Edge Remote Evaluation
In security-sensitive contexts demanding immediate validation bypassing local caches, client.evaluateFlagRemote() performs a direct edge network query to POST /sdk/evaluate, ensuring the latest server-side flag determination in real-time.
import com.toggleai.sdk.ToggleAIClient
import com.toggleai.sdk.ToggleAIOptions
import com.toggleai.sdk.EvaluationContext
// Create client
val client = ToggleAIClient(
ToggleAIOptions(
clientId = "pk_live_xxx",
secret = "sk_live_xxx",
pollingIntervalMs = 30_000,
defaultContext = EvaluationContext(
attributes = mapOf("server_region" to "us-east-1")
),
)
)
// Initialize (suspend function β call from coroutine)
client.init()
// Evaluate flags
val context = EvaluationContext(
userId = "user_123",
attributes = mapOf("plan" to "premium", "country" to "US"),
)
if (client.getFlag("new-checkout", context)) {
showNewCheckout()
}
// Typed flag value
val color = client.getFlagValue<String>("button-color", context, "#000000")
val maxItems = client.getFlagValue<Int>("max-items", context, 10)
// Remote config
val timeout = client.getConfig<Int>("api_timeout_ms", 5000)
// Cleanup
client.close()Application Class
class ToggleAIApp : Application() {
lateinit var toggleai: ToggleAIClient
private set
override fun onCreate() {
super.onCreate()
toggleai = ToggleAIClient(
ToggleAIOptions(
clientId = BuildConfig.TOGGLEAI_CLIENT_ID,
secret = BuildConfig.TOGGLEAI_SECRET,
pollingIntervalMs = 60_000, // poll less on mobile
context = this, // Pass application context to capture device platform details
)
)
// Initialize in a coroutine scope
ProcessLifecycleOwner.get().lifecycleScope.launch {
try {
toggleai.init()
Log.d("ToggleAI", "SDK initialized")
} catch (e: Exception) {
Log.e("ToggleAI", "Init failed", e)
}
}
}
}Usage in Activities / Fragments
class CheckoutActivity : AppCompatActivity() {
private val toggleai get() = (application as ToggleAIApp).toggleai
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val userId = FirebaseAuth.getInstance().currentUser?.uid ?: "anonymous"
val context = EvaluationContext(
userId = userId,
attributes = mapOf(
"platform" to "android",
"app_version" to BuildConfig.VERSION_NAME,
),
)
if (toggleai.getFlag("new-checkout-ui", context)) {
setContentView(R.layout.activity_checkout_new)
} else {
setContentView(R.layout.activity_checkout_legacy)
}
// Read remote config
val timeout = toggleai.getConfig<Int>("checkout_timeout_ms", 10_000)
}
}Jetpack Compose
@Composable
fun CheckoutScreen(toggleai: ToggleAIClient) {
val context = remember {
EvaluationContext(
userId = currentUserId(),
attributes = mapOf("platform" to "android"),
)
}
val showNewUI = remember { toggleai.getFlag("new-checkout-ui", context) }
val buttonColor = remember {
toggleai.getFlagValue<String>("checkout-btn-color", context, "#2196F3")
}
if (showNewUI) {
NewCheckoutUI(buttonColor = Color(android.graphics.Color.parseColor(buttonColor)))
} else {
LegacyCheckoutUI()
}
}Gradle Configuration
android {
defaultConfig {
minSdkVersion 21
buildConfigField "String", "TOGGLEAI_CLIENT_ID",
""" + (project.findProperty("TOGGLEAI_CLIENT_ID") ?: "") + """
buildConfigField "String", "TOGGLEAI_SECRET",
""" + (project.findProperty("TOGGLEAI_SECRET") ?: "") + """
}
}
dependencies {
implementation("com.toggleai:sdk-kotlin:1.0.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}Network operations (init(), evaluateFlagRemote(), flush()) are suspend functions. Local evaluation is synchronous and safe to call from any thread.
// Suspend functions β call from coroutines
lifecycleScope.launch {
client.init()
val result = client.evaluateFlagRemote("dark-mode", context)
println("Remote result: ${result.reason}")
}
// Synchronous β safe from any thread
val enabled = client.getFlag("dark-mode", context) // instant, from cache
val timeout = client.getConfig<Int>("timeout_ms", 5000) // instant, from cacheimport com.toggleai.sdk.ToggleAIException
try {
client.init()
} catch (e: ToggleAIException) {
when (e.code) {
"INVALID_KEY" -> Log.e("ToggleAI", "Bad credentials")
"RATE_LIMITED" -> Log.e("ToggleAI", "Rate limited")
"NETWORK_ERROR" -> Log.e("ToggleAI", "Cannot reach API")
else -> Log.e("ToggleAI", "Error: ${e.message}")
}
}
// Logging errors
val logger = client.getLogger()
try {
riskyOperation()
} catch (e: Exception) {
logger.captureError(e, mapOf("screen" to "checkout"))
}
// Flush before app closes
logger.flush()| Method | Returns | Description |
|---|---|---|
init() | suspend | Fetch config, start polling |
close() | suspend | Stop polling, flush logs |
refresh() | suspend | Manually refresh config |
getFlag(key, ctx?, default?) | Boolean | Boolean flag, local eval |
getFlagValue<T>(key, ctx?, default?) | T? | Typed flag value |
evaluateFlag(key, ctx?) | FlagEvaluationResult | Full evaluation |
evaluateFlagRemote(key, ctx?) | suspend β Result | Server-side eval |
getConfig<T>(key, default?) | T? | Typed config value |
getAllConfigs() | Map<String, Any?> | All config values |
hasConfig(key) | Boolean | Key existence check |
getLogger() | ToggleAILogger | Get attached logger |
logger.info(msg, ctx?) | β | Log info |
logger.captureError(err, ctx?) | β | Capture exception |
logger.flush() | suspend | Flush queued events |