
Simplifies platform permission flows by exposing the real state machine, stateless-by-default with optional BYO storage, sealed permission model, crash-safe API, Compose-native controller and DI-agnostic integrations.
आज्ञा, Sanskrit for permission, consent.
A small, opinionated Kotlin Multiplatform permission library for Android and iOS.
Built so you stop reimplementing the same shouldShowRequestPermissionRationale /
CLAuthorizationStatus dance in every app.
Permissions on Android and iOS are not the same shape:
Most libraries paper over this with the lowest common denominator (one ask, ever) and force you to pick a storage strategy. Aagya does neither.
It exposes the real state machine:
NotDetermined
becomes Granted (user allows)
becomes Denied(canAskAgain = true) (request again)
becomes Denied(canAskAgain = false) (open Settings)
…and lets you decide if you want to layer a stricter app policy on top (with your storage of choice).
shouldShowRequestPermissionRationale on Android and CLAuthorizationStatus on iOS as the source of truth. Zero storage required for the common case.:store-datastore (Android) and :store-userdefaults (iOS) adapters ship in the box.rememberPermissionController() for Compose users; plain interface for non-Compose KMP code.:di-koin module if you use Koin. Otherwise, build it yourself with rememberPermissionController().// build.gradle.kts (KMP shared module)
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.ksharma-xyz:aagya-data:0.1.0")
}
}
}@Composable
fun LocationButton() {
val controller = rememberPermissionController()
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
when (val result = controller.requestPermission(AppPermission.Location.Fine)) {
is PermissionResult.Granted -> startLocationFlow()
is PermissionResult.Denied -> if (!result.canAskAgain) controller.openAppSettings()
is PermissionResult.Cancelled -> Unit
}
}
}) {
Text("Use my location")
}
}That's it. No singletons, no Application subclass to extend, no storage to set up.
val controller = rememberPermissionController(
policy = PermissionPolicy(
maxRequestsAndroid = 1,
maxRequestsIos = 1,
store = rememberDataStorePermissionStore(),
),
)See recipes for stricter policies, custom storage, and DI integration.
| Artifact | Purpose | Required? |
|---|---|---|
io.github.ksharma-xyz:aagya-state |
Pure-Kotlin types: AppPermission, PermissionStatus, PermissionResult, PermissionPolicy. |
yes |
io.github.ksharma-xyz:aagya-data |
PermissionController interface and Android/iOS implementations. |
yes |
io.github.ksharma-xyz:aagya-store-datastore |
Android PermissionStore backed by Jetpack DataStore. |
optional |
io.github.ksharma-xyz:aagya-store-userdefaults |
iOS PermissionStore backed by NSUserDefaults. |
optional |
io.github.ksharma-xyz:aagya-di-koin |
Koin module factory if you use Koin. | optional |
iosArm64, iosSimulatorArm64)JVM and JS targets may follow if there is real demand. Open an issue.
v0.1 ships only Location.Fine and Location.Coarse. The sealed hierarchy already
includes stubs for these so adding them is non-breaking:
CameraMicrophoneNotificationsPhotos (read / read-write split for iOS 14+)Calendar, Contacts
See CONTRIBUTING.md. PRs welcome. Please open an issue before any non-trivial work so we can agree on the shape of the API.
Apache 2.0. Use it however you want.
Aagya is named for आज्ञा, the Sanskrit word for permission / command. The library gives you a clean way to ask the user for theirs.
आज्ञा, Sanskrit for permission, consent.
A small, opinionated Kotlin Multiplatform permission library for Android and iOS.
Built so you stop reimplementing the same shouldShowRequestPermissionRationale /
CLAuthorizationStatus dance in every app.
Permissions on Android and iOS are not the same shape:
Most libraries paper over this with the lowest common denominator (one ask, ever) and force you to pick a storage strategy. Aagya does neither.
It exposes the real state machine:
NotDetermined
becomes Granted (user allows)
becomes Denied(canAskAgain = true) (request again)
becomes Denied(canAskAgain = false) (open Settings)
…and lets you decide if you want to layer a stricter app policy on top (with your storage of choice).
shouldShowRequestPermissionRationale on Android and CLAuthorizationStatus on iOS as the source of truth. Zero storage required for the common case.:store-datastore (Android) and :store-userdefaults (iOS) adapters ship in the box.rememberPermissionController() for Compose users; plain interface for non-Compose KMP code.:di-koin module if you use Koin. Otherwise, build it yourself with rememberPermissionController().// build.gradle.kts (KMP shared module)
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.ksharma-xyz:aagya-data:0.1.0")
}
}
}@Composable
fun LocationButton() {
val controller = rememberPermissionController()
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
when (val result = controller.requestPermission(AppPermission.Location.Fine)) {
is PermissionResult.Granted -> startLocationFlow()
is PermissionResult.Denied -> if (!result.canAskAgain) controller.openAppSettings()
is PermissionResult.Cancelled -> Unit
}
}
}) {
Text("Use my location")
}
}That's it. No singletons, no Application subclass to extend, no storage to set up.
val controller = rememberPermissionController(
policy = PermissionPolicy(
maxRequestsAndroid = 1,
maxRequestsIos = 1,
store = rememberDataStorePermissionStore(),
),
)See recipes for stricter policies, custom storage, and DI integration.
| Artifact | Purpose | Required? |
|---|---|---|
io.github.ksharma-xyz:aagya-state |
Pure-Kotlin types: AppPermission, PermissionStatus, PermissionResult, PermissionPolicy. |
yes |
io.github.ksharma-xyz:aagya-data |
PermissionController interface and Android/iOS implementations. |
yes |
io.github.ksharma-xyz:aagya-store-datastore |
Android PermissionStore backed by Jetpack DataStore. |
optional |
io.github.ksharma-xyz:aagya-store-userdefaults |
iOS PermissionStore backed by NSUserDefaults. |
optional |
io.github.ksharma-xyz:aagya-di-koin |
Koin module factory if you use Koin. | optional |
iosArm64, iosSimulatorArm64)JVM and JS targets may follow if there is real demand. Open an issue.
v0.1 ships only Location.Fine and Location.Coarse. The sealed hierarchy already
includes stubs for these so adding them is non-breaking:
CameraMicrophoneNotificationsPhotos (read / read-write split for iOS 14+)Calendar, Contacts
See CONTRIBUTING.md. PRs welcome. Please open an issue before any non-trivial work so we can agree on the shape of the API.
Apache 2.0. Use it however you want.
Aagya is named for आज्ञा, the Sanskrit word for permission / command. The library gives you a clean way to ask the user for theirs.