
Simplifies permission management in projects with a Compose-friendly API, focusing on modern platforms by dropping older iOS support and adapting to Apple's latest changes.
KmmPermissions is inspired by the Moko-Permissions library, sharing many similarities. However, the key difference is its focus on modern platforms—dropping support for older iOS devices and adapting to the latest changes introduced by Apple.
Note: A bug has been reported to the Moko team but remains unresolved (issue #119).
This library consists of three core components:
PermissionControllerPermissionStateBindEffect composable functionAdd the following dependency to your shared module's build.gradle.kts file:
implementation("com.lynxal.permissions:permissions:0.0.6")You need to create a PermissionControllerImpl for your specific platform (Android or iOS). You can use any Dependency Injection (DI) framework or instantiate it manually.
appContext is provided when creating the controller.Here’s an example implementation in a ViewModel or ScreenModel:
// For Android
val permissionController = PermissionControllerImpl(appContext)
// For iOS
val permissionController = PermissionControllerImpl()Note: Holding a reference to appContext is acceptable. However, the BindEffect composable will clear its internal (weak) reference to appContext after the screen disappears.
The BindEffect composable function should be called from the root of your screen’s composition function. This ensures proper lifecycle handling. There’s no need to hoist the call to higher levels.
@Composable
override fun LocationPermissionRequestScreen() {
val viewModel = ...
// Place the BindEffect call at the root of the screen
BindEffect(viewModel.permissionController)
}Note: The PermissionController instance remains constant and does not change over time.
In your ViewModel or ScreenModel, define an instance variable to track the permission request result. Typically, you can initialize it as follows:
val permissionState = mutableStateOf<PermissionState>(PermissionState.UNKNOWN)Use the requestPermissionState method to check the current permission state. For example, to verify access to Bluetooth Low Energy (BLE) functionality:
permissionController.requestPermissionState(Permission.BLUETOOTH_LE)Create a method in your ViewModel or ScreenModel to request permissions for a specific resource. Handle exceptions as needed and update the permission state accordingly.
fun requestPermission() {
try {
permissionController.requestPermission(Permission.BLUETOOTH_LE)
} catch (e: PermissionException) {
Logger.error("Failed to request Bluetooth permissions", e)
}
permissionState.value = permissionController.requestPermissionState(Permission.BLUETOOTH_LE)
}Observe the permissionState from your composable function. Ensure that the observation is as close as possible to where the value is being used. Any change in permissionState will trigger recomposition of the relevant UI segment.
val permissionState by remember { homeViewContract.permissionState }
// Adjust the UI based on the permission state
when (permissionState) {
PermissionState.DENIED, PermissionState.DENIED_ALWAYS -> { /* Handle denied state */ }
PermissionState.UNKNOWN, PermissionState.UNDETERMINED -> { /* Handle unknown state */ }
PermissionState.UNAVAILABLE -> { /* Handle unavailable state */ }
PermissionState.GRANTED -> { /* Handle granted state */ }
}FINE_LOCATION
COARSE_LOCATION
BLUETOOTH_LE
BLUETOOTH_SCAN
BLUETOOTH_ADVERTISE
BLUETOOTH_CONNECT
NOTIFICATIONS
READ_STORAGE
WRITE_STORAGE - At this moment write to external storage is not supported on Android. We are working on this
GALLERY
CAMERA
The KmmPermissions library simplifies permission management in KMM projects. It provides a Compose-friendly API and platform-specific support for Android and iOS.
For issues, suggestions, or contributions, feel free to open a pull request or issue on the repository.
KmmPermissions is inspired by the Moko-Permissions library, sharing many similarities. However, the key difference is its focus on modern platforms—dropping support for older iOS devices and adapting to the latest changes introduced by Apple.
Note: A bug has been reported to the Moko team but remains unresolved (issue #119).
This library consists of three core components:
PermissionControllerPermissionStateBindEffect composable functionAdd the following dependency to your shared module's build.gradle.kts file:
implementation("com.lynxal.permissions:permissions:0.0.6")You need to create a PermissionControllerImpl for your specific platform (Android or iOS). You can use any Dependency Injection (DI) framework or instantiate it manually.
appContext is provided when creating the controller.Here’s an example implementation in a ViewModel or ScreenModel:
// For Android
val permissionController = PermissionControllerImpl(appContext)
// For iOS
val permissionController = PermissionControllerImpl()Note: Holding a reference to appContext is acceptable. However, the BindEffect composable will clear its internal (weak) reference to appContext after the screen disappears.
The BindEffect composable function should be called from the root of your screen’s composition function. This ensures proper lifecycle handling. There’s no need to hoist the call to higher levels.
@Composable
override fun LocationPermissionRequestScreen() {
val viewModel = ...
// Place the BindEffect call at the root of the screen
BindEffect(viewModel.permissionController)
}Note: The PermissionController instance remains constant and does not change over time.
In your ViewModel or ScreenModel, define an instance variable to track the permission request result. Typically, you can initialize it as follows:
val permissionState = mutableStateOf<PermissionState>(PermissionState.UNKNOWN)Use the requestPermissionState method to check the current permission state. For example, to verify access to Bluetooth Low Energy (BLE) functionality:
permissionController.requestPermissionState(Permission.BLUETOOTH_LE)Create a method in your ViewModel or ScreenModel to request permissions for a specific resource. Handle exceptions as needed and update the permission state accordingly.
fun requestPermission() {
try {
permissionController.requestPermission(Permission.BLUETOOTH_LE)
} catch (e: PermissionException) {
Logger.error("Failed to request Bluetooth permissions", e)
}
permissionState.value = permissionController.requestPermissionState(Permission.BLUETOOTH_LE)
}Observe the permissionState from your composable function. Ensure that the observation is as close as possible to where the value is being used. Any change in permissionState will trigger recomposition of the relevant UI segment.
val permissionState by remember { homeViewContract.permissionState }
// Adjust the UI based on the permission state
when (permissionState) {
PermissionState.DENIED, PermissionState.DENIED_ALWAYS -> { /* Handle denied state */ }
PermissionState.UNKNOWN, PermissionState.UNDETERMINED -> { /* Handle unknown state */ }
PermissionState.UNAVAILABLE -> { /* Handle unavailable state */ }
PermissionState.GRANTED -> { /* Handle granted state */ }
}FINE_LOCATION
COARSE_LOCATION
BLUETOOTH_LE
BLUETOOTH_SCAN
BLUETOOTH_ADVERTISE
BLUETOOTH_CONNECT
NOTIFICATIONS
READ_STORAGE
WRITE_STORAGE - At this moment write to external storage is not supported on Android. We are working on this
GALLERY
CAMERA
The KmmPermissions library simplifies permission management in KMM projects. It provides a Compose-friendly API and platform-specific support for Android and iOS.
For issues, suggestions, or contributions, feel free to open a pull request or issue on the repository.