Examples

Jetpack Compose

A complete Compose app with an application-scoped AirStrings instance, reactive string collection, and ICU plural formatting.

A minimal but complete Android app using the AirStrings Android SDK with Jetpack Compose. One application-scoped instance, provided to the composition tree, collected reactively in composables. For every configuration field in detail, see the Android SDK reference.

Strings used in this example

KeyFormatValue
home.welcome_titletextWelcome!
home.items_counticu{count, plural, one {# item} other {# items}}

Add the dependencies

The SDK is distributed via JitPack. In settings.gradle.kts:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven("https://jitpack.io")
    }
}

In your module's build.gradle.kts, add the SDK and the lifecycle-aware Compose collector:

dependencies {
    implementation("com.github.symbionix-sl:airstrings-sdk-android:v1.1.1")
    implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
}

Create the instance in your Application

AirStrings.create is application-scoped: it lives for the process lifetime, loads the cache immediately, and refreshes in the background and on foreground return.

import android.app.Application
import com.airstrings.sdk.AirStrings
import com.airstrings.sdk.AirStringsConfiguration

class DemoApplication : Application() {

    lateinit var airStrings: AirStrings
        private set

    override fun onCreate() {
        super.onCreate()
        airStrings = AirStrings.create(
            this,
            AirStringsConfiguration(
                organizationId = "org_...",
                projectId = "proj_...",
                environmentId = "env_...",
                publicKeys = listOf("pk_..."),
            ),
        )
    }
}

Register it in AndroidManifest.xml with android:name=".DemoApplication" on the application element.

Provide it to the composition

Provide the instance once at the root with CompositionLocalProvider, then any composable can reach it through LocalAirStrings.

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.CompositionLocalProvider
import com.airstrings.sdk.compose.LocalAirStrings

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val airStrings = (application as DemoApplication).airStrings
        setContent {
            CompositionLocalProvider(LocalAirStrings provides airStrings) {
                WelcomeScreen()
            }
        }
    }
}

Collect and render

Collect the strings StateFlow with collectAsStateWithLifecycle() for reactive reads, and use format() for ICU plurals.

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.airstrings.sdk.compose.LocalAirStrings

@Composable
fun WelcomeScreen() {
    val airStrings = LocalAirStrings.current
    val strings by airStrings.strings.collectAsStateWithLifecycle()

    Column {
        Text(strings["home.welcome_title"] ?: "home.welcome_title")
        Text(airStrings.format("home.items_count", mapOf("count" to 5)))
    }
}

Gotcha: subscript access (airStrings["key"]) reads strings.value synchronously and does not trigger recomposition. In Compose, always collect the strings StateFlow via collectAsStateWithLifecycle() so your UI updates when a new bundle lands. Subscript access is for non-Compose code: ViewModels, services, one-shot reads.

On this page