This library, using Kotlin Coroutines, provides an easy way to interact with Android Runtime Permissions
- Only Coroutines and AndroidX
- Designed for using in ViewModel/Presenter/etc
- Observe permissions statuses changes by Coroutines Flow
- Easy handle multiple permissions requests
- No hurt with lifecycle, rotating, DKA - just working in CoroutineScope
- No callbacks
- No additional activities
- Request queue - everything will be ok, even if you make several requests from different CoroutineScope at the same time
Library for processing permission states using dialogs in accordance with Google recommendations
- Also, all the advantages of mintpermissions
- Easy to customize behavior and display with FlowConfig
- DialogsFlow for those cases when there is simply some kind of button on which an action must occur that requires permission
- PlainFlow for those cases when there is some kind of full screen content (for example, creating youtube shorts) and you need to display the permission status right inside the screen. Internally, DialogFlow is used with special settings
// Root build.gradle:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
// Target module's build.gradle:
dependencies {
implementation 'com.github.mintrocket.MintPermissions:mintpermissions:1.1.3'
// if you need ready processing of permissions with dialogs
implementation 'com.github.mintrocket.MintPermissions:mintpermissions-flows:1.1.3'
}
Android SDK: Minimum API level is 15
AndroidX: this library requires AndroidX
Coroutines: this library requires Kotlin Coroutines
To get started, you can install ExampleApp and explore its source code
By default library automatically working with activities. Just add this in your Application.
class App : Application() {
override fun onCreate() {
super.onCreate()
initMintPermissions()
// if you used "mintpermissions-flows"
initMintPermissionsFlow()
}
}
If you want manually working with activities, add config. But you should add initMintPermissionsManager()
in every activities where permissions might be needed
class App : Application() {
override fun onCreate() {
super.onCreate()
initMintPermissions(MintPermissionsConfig(autoInitManagers = false))
// if you used "mintpermissions-flows"
initMintPermissionsFlow(MintPermissionsConfig(autoInitManagers = false))
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initMintPermissionsManager()
// if you used "mintpermissions-flows"
initMintPermissionsFlowManager()
}
}
If you love and respect DI, you also can do something like that (Koin for example)
val libraryModule = module {
single { MintPermissions.controller }
factory { MintPermissions.createManager() }
}
class SampleViewModel(
private val permissionsController: MintPermissionsController
) : ViewModel() {
companion object {
private val cameraPermissions = listOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
)
}
// Update ui by permissions changes
val statuses = permissionsController.observe(cameraPermissions)
fun onActionClick() {
viewModelScope.launch {
val result = permissionsController.request(cameraPermissions)
if (result.isAllGranted()) {
// handle granted
return@launch
}
val denied = result.filterDenied()
val needsRationale = result.filterNeedsRationale()
}
}
}
class SampleViewModel(
private val permissionsDialogFlow: MintPermissionsDialogFlow
) : ViewModel() {
companion object {
private val cameraPermissions = listOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
)
}
fun onActionClick() {
viewModelScope.launch {
val result = permissionsDialogFlow.request(cameraPermissions)
if (result.isSuccess()) {
// handle all permissions granted
} else {
// handle any permission not granted or dialog canceled
}
}
}
}
Useful for cases where the status of permissions needs to be displayed on the screen itself
class SampleViewModel : ViewModel() {
companion object {
private val cameraPermissions = listOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
)
}
private val permissionsPlainFlow = MintPermissionsFlow.createPlainFlow(cameraPermissions)
// Use for update screen
val notGrantedFlow: Flow<List<MintPermissionStatus>> = permissionsPlainFlow.observeNotGranted()
fun onActionClick() {
viewModelScope.launch {
val result = permissionsPlainFlow.request()
if (result.isSuccess()) {
// handle all permissions granted
} else {
// handle any permission not granted or dialog canceled
}
}
}
}
Library can detect these statuses
- Granted - when permission granted
- Denied - when "never requested" and "permanently denied"
- NeedsRationale - when needs rationale
- NotFound - when not found in declared permissions in app manifest
But in some other libraries, you might see statuses like "cancelled, denied permanently, just denied, etc." - this is impossible to detect.
In other libraries, they combine Status and Action, which is formed when Status changes.
In this library, these concepts are separated.
Available only in MintPermissionResult. Library can detect these actions
- Granted - when status changed "not granted" -> "granted"
- NeedsRationale - when status changed "not needs rationale" -> "needs rationale"
- DeniedPermanently - when status changed "not denied" -> "denied"
- status - permission status
- nullable action - action that appears if the status before and after does not match
- fun observe(permission: MintPermission) - observe single permission, returns single status
- fun observe(permissions: List<MintPermission>) - observe multiple permissions, returns list of status
- fun observeAll() - observe all declared permissions, returns list of status
- fun get(permission: MintPermission) - get single permission, returns single status
- fun get(permissions: List<MintPermission>) - get multiple permissions, returns list of status
- fun getAll() - get all declared permissions, returns list of status
- fun request(permission: MintPermission) - request single permission, returns single result
- fun request(permissions: List<MintPermission>) - request single permission, returns list of result
If you pass non-existent or undeclared permissions, the library will return MintPermissionStatus.NotFound.
All observe* and get* methods returns "cached" information about permissions statuses. Values are updated on focus change and onResume in activity.
There are more than 40 useful Extensions for working with Status, Action, Result - Source Code
Be sure to review the changes list before updating the version
If you find any bug, or you have suggestions, don't be shy to create issues or make a PRs in the develop
branch.