Skip to content

brewkits/Grant

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Grant Logo

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.

Maven Central Kotlin Platform 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 DocumentationQuick StartWhy Grant?Demo App


🚀 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 Testing782 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)

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)

@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.

// 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

// 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.

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.


📖 Deep Dives

Guide Description
Architecture How concurrency, state machines, and the mutex flow work
iOS Setup Critical Info.plist configuration — read before shipping
Migration Guide Upgrading from v1.2.x to v1.3.1
Service Checking Combining permission + hardware service checks
Manual Injection Using Grant without any DI framework
Android Reliability How we fix "Dead Clicks" on Android
Best Practices 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.
  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 for details.

Built with ❤️ by BrewKits