https://github.com/brewkits/Grant
Kotlin Multiplatform permission library for Android & iOS. No Fragment/Activity needed, ViewModel-first, Compose Multiplatform ready. Fixes Android dead clicks & iOS deadlocks.
https://github.com/brewkits/Grant
android android-14-permission bluetooth clean-architecture compose-multiplatform compose-multiplatform-permission coroutines gps ios ios-17-permission jetpack-compose kmp kotlin-multiplatform kotlin-multiplatform-permission moko-permissions-alternative mvvm nfc permission permissions runtime-permissions
Last synced: about 1 month ago
JSON representation
Kotlin Multiplatform permission library for Android & iOS. No Fragment/Activity needed, ViewModel-first, Compose Multiplatform ready. Fixes Android dead clicks & iOS deadlocks.
- Host: GitHub
- URL: https://github.com/brewkits/Grant
- Owner: brewkits
- License: apache-2.0
- Created: 2026-01-22T15:01:45.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-04-29T02:00:28.000Z (about 1 month ago)
- Last Synced: 2026-04-29T04:04:02.539Z (about 1 month ago)
- Topics: android, android-14-permission, bluetooth, clean-architecture, compose-multiplatform, compose-multiplatform-permission, coroutines, gps, ios, ios-17-permission, jetpack-compose, kmp, kotlin-multiplatform, kotlin-multiplatform-permission, moko-permissions-alternative, mvvm, nfc, permission, permissions, runtime-permissions
- Language: Kotlin
- Homepage: https://www.brewkits.dev
- Size: 1.27 MB
- Stars: 85
- Watchers: 3
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
- kmp-awesome - Grant - Permission library for Android & iOS (Libraries / π± Device)
README

# Grant: Robust Permission Management for KMP
**Production-ready, type-safe permission handling for Kotlin Multiplatform β handling the complex edge cases of Android and iOS flows.**
[](https://central.sonatype.com/artifact/dev.brewkits/grant-core)
[](https://kotlinlang.org)
[](https://kotlinlang.org/docs/multiplatform.html)
[](LICENSE)
---
### β‘ Zero Boilerplate. Zero Lifecycle Binding. Zero Headache.
Grant is not just another permission library. It is a **production-hardened engine** designed to handle complex edge cases that lead to crashes and hangs in other solutions. Built for professionals who demand absolute reliability.
[**Explore Documentation**](docs/README.md) β’ [**Quick Start**](#-quick-start) β’ [**Why Grant?**](#-why-grant) β’ [**Demo App**](#-demo)
---
## π Killer Features
- **π― Pure Logic-First API** β Works anywhere: ViewModels, Repositories, or Composables. **No Activity or Fragment references required.**
- **π iOS Framework Isolation** β Each permission type is isolated to its own handler, preventing unused Apple frameworks (Location, Bluetooth, Motion, etc.) from being linked into your binary. No more phantom `NSUsageDescription` requirements.
- **π‘οΈ iOS Crash-Guard** β Automatically validates `Info.plist` keys before requesting, preventing the dreaded `SIGABRT` production crashes.
- **π Android Process-Death Resilience** β The only library that handles system-initiated process death gracefully with zero timeouts.
- **β‘ iOS Deadlock Fix** β Built-in protection against the infamous Camera/Microphone first-request deadlock.
- **π¦ 17 Native Permissions** β Deep, native integration for Camera, Gallery (Partial access!), Location, Bluetooth, Motion, Health, and more.
- **π οΈ Service Intelligence** β Don't just check permissions; check if services (GPS, Bluetooth, Health) are actually enabled.
- **π§© Custom Extensibility** β Use `RawPermission` to support new OS permissions (Android 15+, iOS 18+) instantly without library updates.
- **π§ͺ Ultra-Robust Testing** β **782 automated tests** (423 Android + 359 iOS Simulator) covering every platform edge case, state invariant, and UI interaction. 100% pass rate.
---
## π The "Grant" Experience
### 1οΈβ£ Define your logic (Logic Layer)
```kotlin
class CameraViewModel(private val grantManager: GrantManager) : ViewModel() {
val cameraGrant = GrantHandler(
grantManager = grantManager,
grant = AppGrant.CAMERA,
scope = viewModelScope
)
fun capturePhoto() {
cameraGrant.request {
// Only runs when permission is FULLY granted
cameraEngine.startCapture()
}
}
}
```
### 2οΈβ£ Drop in the UI (Presentation Layer)
```kotlin
@Composable
fun CameraScreen(viewModel: CameraViewModel) {
// Handles Rationale, Denied, and Settings dialogs automatically
GrantDialog(handler = viewModel.cameraGrant)
IconButton(onClick = { viewModel.capturePhoto() }) {
Icon(Icons.Default.Camera, contentDescription = "Capture")
}
}
```
### π Best Practice: The Full Readiness Check (Logic + Hardware)
Permission is only half the battle. In production, you also need to check if the hardware service (GPS, Bluetooth) is actually enabled.
```kotlin
// Use GrantAndServiceChecker to combine both worlds
class LocationViewModel(
private val checker: GrantAndServiceChecker,
private val grantManager: GrantManager
) : ViewModel() {
fun startTracking() {
viewModelScope.launch {
when (val status = checker.checkLocationReady()) {
LocationReadyStatus.Ready -> sensor.start()
LocationReadyStatus.ServiceDisabled -> _uiState.showEnableGPS()
LocationReadyStatus.GrantDenied -> requestPermission()
LocationReadyStatus.BothRequired -> _uiState.showTotalFailure()
}
}
}
}
```
---
## βοΈ Why Grant?
Most KMP permission libraries are simple wrappers around native APIs. Grant is an **Architectural Solution**.
| Feature | **Grant** | moko-permissions | accompanist-permissions |
| :--- | :---: | :---: | :---: |
| **No Lifecycle Binding** | β
| β (needs BindEffect) | β (needs Activity) |
| **ViewModel Support** | **Full** | Partial | β |
| **iOS Crash Prevention** | β
| β | β |
| **iOS Framework Isolation** | β
| β | N/A |
| **Android Deadlock Fix** | β
| β | β |
| **Process Death Recovery** | **Native** | β | Manual |
| **Service Checks (GPS/BT/Health)** | β
| β | β |
| **Android 14 Partial Access** | β
| Partial | β
|
| **Custom Permissions** | β
| Limited | Limited |
---
## πΊοΈ Platform Support & Coverage
| Permission | Android | iOS | Notes |
| :--- | :---: | :---: | :--- |
| **Camera** | β
| β
| iOS main-thread safe + deadlock fix |
| **Microphone** | β
| β
| Shares AVFoundation handler with Camera |
| **Gallery (full)** | β
| β
| Android 14+ partial access (`PARTIAL_GRANTED`) |
| **Gallery (images only)** | β
| β
| `AppGrant.GALLERY_IMAGES_ONLY` |
| **Gallery (video only)** | β
| β
| `AppGrant.GALLERY_VIDEO_ONLY` |
| **Storage (legacy)** | β
| β
| Pre-API 33 fallback |
| **Location (when in use)** | β
| β
| Intelligent GPS service check included |
| **Location (always)** | β
| β
| Android 2-step background flow handled |
| **Notifications** | β
| β
| Android 13+ and legacy flows |
| **Bluetooth** | β
| β
| Service status check + Scan/Connect |
| **Bluetooth Advertise** | β
| β
| `AppGrant.BLUETOOTH_ADVERTISE` |
| **Contacts (full)** | β
| β
| Read + Write access |
| **Contacts (read-only)** | β
| β
| `AppGrant.READ_CONTACTS` |
| **Calendar (full)** | β
| β
| iOS 17+ `FullAccess` / `WriteOnly` mapped correctly |
| **Calendar (read-only)** | β
| β
| `AppGrant.READ_CALENDAR` |
| **Motion / Activity** | β
| β
| Simulator-aware (safe mock on Simulator) |
| **Schedule Exact Alarm** | β
| β
| Android 12+ `SCHEDULE_EXACT_ALARM` |
### Service Checks (`ServiceType`)
| Service | Android | iOS |
| :--- | :---: | :---: |
| **GPS / Location** | β
| β
|
| **Bluetooth** | β
| β
|
| **Wi-Fi** | β
| β
|
| **NFC** | β
| β |
| **Camera hardware** | β
| β
|
| **Health Connect / HealthKit** | β
| β
|
---
## π¦ Installation
```kotlin
// shared/build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation("dev.brewkits:grant-core:1.3.1")
implementation("dev.brewkits:grant-compose:1.3.1") // Optional: Compose dialogs
implementation("dev.brewkits:grant-core-koin:1.3.1") // Optional: Koin DI support
}
}
}
```
> [!IMPORTANT]
> For projects targeting **Web (JS)** or **Desktop (JVM)**, use an intermediate `mobileMain` source set to avoid linking iOS/Android dependencies on unsupported platforms. [Read the Guide](docs/DEPENDENCY_MANAGEMENT.md).
> [!NOTE]
> **Koin users**: The Koin integration was moved to `grant-core-koin` in v1.3.1. Add the new artifact alongside `grant-core` and replace `GrantPlatformModule` imports. See the [Migration Guide](docs/MIGRATION_GUIDE.md).
---
## π Deep Dives
| Guide | Description |
| :--- | :--- |
| [Architecture](docs/grant-core/ARCHITECTURE.md) | How concurrency, state machines, and the mutex flow work |
| [iOS Setup](docs/platform-specific/ios/info-plist.md) | Critical `Info.plist` configuration β read before shipping |
| [Migration Guide](docs/MIGRATION_GUIDE.md) | Upgrading from v1.2.x to v1.3.1 |
| [Service Checking](docs/grant-core/SERVICES.md) | Combining permission + hardware service checks |
| [Manual Injection](docs/MANUAL_INJECTION.md) | Using Grant without any DI framework |
| [Android Reliability](docs/FIX_DEAD_CLICK_ANDROID.md) | How we fix "Dead Clicks" on Android |
| [Best Practices](docs/BEST_PRACTICES.md) | Patterns for production apps |
---
## π€ Contributing
We are on a mission to make permissions a "solved problem" for KMP. Join us!
1. Check out [CONTRIBUTING.md](CONTRIBUTING.md).
2. Run `./gradlew :grant-core:allTests` to ensure stability.
3. Submit your PR.
---
## βοΈ License
Grant is licensed under the **Apache License 2.0**. See [LICENSE](LICENSE) for details.
Built with β€οΈ by BrewKits