Crash handling¶
Aagya is designed so that the host app never has to wrap calls in try/catch. The public API does not throw across the bridge. This page documents what can go wrong and how Aagya translates it.
What can throw¶
Exactly one thing: construction. If rememberPermissionController() is invoked inside a Composable whose Context chain has no ComponentActivity, Aagya throws IllegalStateException with a pointer to the docs.
This is intentional, it is a developer error, not a runtime condition. Wrapping it in a sealed result would just hide a misuse and lead to silent no-ops in production.
What never throws¶
Every suspend and synchronous method returns a sealed value. Failure modes:
| Symptom | Translation |
|---|---|
Activity is null when launching the picker | PermissionResult.Denied(canAskAgain=true, reason=PresentationUnavailable) |
ActivityResultLauncher.launch(...) throws | PermissionResult.Denied(canAskAgain=true, reason=PlatformError), logged |
CLLocationManager.requestWhenInUseAuthorization throws | same as above, logged |
NSURL.URLWithString(UIApplicationOpenSettingsURLString) is null | openAppSettings() no-ops, logged at warn |
Settings.ACTION_APPLICATION_DETAILS_SETTINGS activity not found | openAppSettings() no-ops, logged at error |
| Aagya policy cap reached | PermissionResult.PolicyExhausted |
Wiring up your logger¶
By default Aagya is silent (NoOpLogger). To see diagnostics, plug in your logger:
class KermitAagyaLogger : Logger {
private val log = co.touchlab.kermit.Logger.withTag("aagya")
override fun debug(message: String) = log.d { message }
override fun info(message: String) = log.i { message }
override fun warn(message: String, error: Throwable?) = log.w(error) { message }
override fun error(message: String, error: Throwable?) = log.e(error) { message }
}
val controller = rememberPermissionController(logger = KermitAagyaLogger())
Good logger hooks for production:
- Crashlytics non-fatal report on
error(...)calls. - Forward
info(...)to your analytics pipeline tagged aspermissionFlow. - Skip
debug(...)in release builds.
What "crash-safe" does not mean¶
Aagya does not handle every conceivable failure mode of Activity or CLLocationManager, only the ones it can plausibly translate. If CLLocationManager itself crashes the process (it shouldn't, but in theory), Aagya can't catch that.
The contract is: the public Aagya API will not be the cause of a crash in your app. Anything beyond that is the platform's responsibility.
Threading¶
If a host app calls a suspend Aagya method from Dispatchers.Default and Aagya needs to touch Activity, it marshals to Dispatchers.Main internally. You don't need to switch dispatchers.