
Expose native age‑range APIs via a Compose-friendly interface with a suspendable age request, sealed result types (range/unknown/unsupported/error), and native data payloads.
Kotlin Multiplatform library for age assurance on Android and iOS. It exposes the native age range APIs of each platform through one Compose-friendly interface and a common sealed result type.
// build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.polstianka:agerange:0.0.1")
}
}
}Targets: android, iosArm64, iosSimulatorArm64.
@Composable
fun AgeGate() {
val provider = rememberAgeRangeProvider()
var result by remember { mutableStateOf<AgeRangeResult?>(null) }
LaunchedEffect(Unit) {
result = provider.requestAge()
}
when (val value = result) {
is AgeRangeResult.Range -> Text("Age: ${value.ageLower}..${value.ageUpper}")
is AgeRangeResult.Unknown -> Text("Age is not available")
AgeRangeResult.LawNotApplies -> Text("No age check in this region")
AgeRangeResult.Unsupported -> Text("Device does not support age assurance")
is AgeRangeResult.Error -> Text("Error: ${value.error.message}")
null -> CircularProgressIndicator()
}
}requestAge() is a suspend function. Call it from a coroutine scope.
interface AgeRangeProvider {
suspend fun requestAge(): AgeRangeResult
}
@Composable
expect fun rememberAgeRangeProvider(): AgeRangeProviderrememberAgeRangeProvider() keeps one provider instance across recompositions and
gives the implementation of the current platform.
| Result | Meaning |
|---|---|
Unsupported |
The device, the operating system version, or the system services do not support age assurance. |
LawApplies.Range |
The age range is available. ageLower and ageUpper are the bounds. A null bound means the range is open on that side. |
LawApplies.Unknown |
The law applies, but the age range is not available yet. The user must do more steps, or the range is not shared. |
LawNotApplies |
The region of the user does not require age assurance. |
Error |
An unexpected exception. The cause is in error. |
LawApplies groups the two results that carry an answer about the user. Match on it
when the region matters more than the exact value:
if (result is AgeRangeResult.LawApplies) {
// The region requires age assurance.
}Every LawApplies result carries a data property with the extra details of the
native API. PlatformAgeRangeData is a marker interface. Cast it in platform source
sets when you need the native fields:
// androidMain
val androidData = result.data as AndroidAgeRangeDataKeep common code free of these casts.
Apache 2.0
Kotlin Multiplatform library for age assurance on Android and iOS. It exposes the native age range APIs of each platform through one Compose-friendly interface and a common sealed result type.
// build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.polstianka:agerange:0.0.1")
}
}
}Targets: android, iosArm64, iosSimulatorArm64.
@Composable
fun AgeGate() {
val provider = rememberAgeRangeProvider()
var result by remember { mutableStateOf<AgeRangeResult?>(null) }
LaunchedEffect(Unit) {
result = provider.requestAge()
}
when (val value = result) {
is AgeRangeResult.Range -> Text("Age: ${value.ageLower}..${value.ageUpper}")
is AgeRangeResult.Unknown -> Text("Age is not available")
AgeRangeResult.LawNotApplies -> Text("No age check in this region")
AgeRangeResult.Unsupported -> Text("Device does not support age assurance")
is AgeRangeResult.Error -> Text("Error: ${value.error.message}")
null -> CircularProgressIndicator()
}
}requestAge() is a suspend function. Call it from a coroutine scope.
interface AgeRangeProvider {
suspend fun requestAge(): AgeRangeResult
}
@Composable
expect fun rememberAgeRangeProvider(): AgeRangeProviderrememberAgeRangeProvider() keeps one provider instance across recompositions and
gives the implementation of the current platform.
| Result | Meaning |
|---|---|
Unsupported |
The device, the operating system version, or the system services do not support age assurance. |
LawApplies.Range |
The age range is available. ageLower and ageUpper are the bounds. A null bound means the range is open on that side. |
LawApplies.Unknown |
The law applies, but the age range is not available yet. The user must do more steps, or the range is not shared. |
LawNotApplies |
The region of the user does not require age assurance. |
Error |
An unexpected exception. The cause is in error. |
LawApplies groups the two results that carry an answer about the user. Match on it
when the region matters more than the exact value:
if (result is AgeRangeResult.LawApplies) {
// The region requires age assurance.
}Every LawApplies result carries a data property with the extra details of the
native API. PlatformAgeRangeData is a marker interface. Cast it in platform source
sets when you need the native fields:
// androidMain
val androidData = result.data as AndroidAgeRangeDataKeep common code free of these casts.
Apache 2.0