-
-
Notifications
You must be signed in to change notification settings - Fork 32
Usage
This page will help you to discover all the currently supported features of this library. The main sections are the following:
- Configuration
- Permission Request
- Check current status
- Runtime handler
- Injection
- Save instance state
- Under the hoods
The main method to start the creation of a request is the extension function permissionsBuilder()
that can be used from an Activity
or a Fragment
.
The only necessary configuration that must be provided to create a new PermissionRequest
is the permission's set that must be requested. Depending on your needs, you can provide one or more permissions for each request.
Example:
// This is the most basic request.
val request = permissionsBuilder(Manifest.permission.CAMERA).build()
You can define also a custom RuntimePermissionHandlerProvider
. If not specified, its default is used (ResultLauncherRuntimePermissionHandlerProvider
).
Example:
val request = permissionsBuilder(Manifest.permission.CAMERA, Manifest.permission.SEND_SMS)
// Specifies a custom RuntimePermissionHandlerProvider.
.runtimeHandlerProvider(MyRuntimePermissionHandlerProvider())
// Build the request
.build()
To find more information about RuntimePermissionHandlerProvider
, go here.
The result received from a permissions request contains a list of PermissionStatus
(List<PermissionStatus>
), one for each requested permission. The result list has the same size and the same order of the list of the requested permissions.
The PermissionStatus
contains the permission which is related to.
The possible statuses which can be received in a callback are:
-
PermissionStatus.Granted
-> the requested permission is granted -
PermissionStatus.Denied.Permanently
-> the requested permission is denied and the user checked "never ask again" in the permissions dialog OR the request is being executed under API 23 (where runtime permissions don't exist) -
PermissionStatus.Denied.ShouldShowRationale
-> the requested permission is denied, but not permanently. This status can't be returned under API 23
So, under API 23 only PermissionStatus.Granted
and PermissionStatus.Denied.Permanently
can be returned depending on their presence in the manifest.
There are several ways to receive the result of a permissions request.
permissionsBuilder(Manifest.permission.CAMERA).build().send { result ->
// Handle the result.
}
You can also add a listener to the request before sending it in one of the following way:
// If you have a centralized management of the events.
request.addListener(this)
// If you want to receive the callback in-line.
request.addListener { result ->
// Handle the result.
}
request.send()
Multiple listeners can be attached to the same request and they can be removed with the following methods:
// Remove a specific listener.
request.removeListener(specificListener)
// Removes all the listeners.
request.removeAllListeners()
val request = permissionsBuilder(Manifest.permission.CAMERA).build()
request.liveData().observe(this) { result ->
// Handle the result.
}
request.send()
You need to add the artifact com.github.fondesa:kpermissions-coroutines
.
launch {
val result = permissionsBuilder(Manifest.permission.CAMERA).build().sendSuspend()
// Handle the result.
}
You need to add the artifact com.github.fondesa:kpermissions-coroutines
and opt-in the experimental API of Flow
.
val request = permissionsBuilder(Manifest.permission.CAMERA).build()
launch {
request.flow().collect { result ->
// Handle the result.
}
}
request.send()
You need to add the artifact com.github.fondesa:kpermissions-coroutines-rx2
if you are using RxJava 2 or the artifact com.github.fondesa:kpermissions-rx3
if you are using RxJava 3.
val request = permissionsBuilder(Manifest.permission.CAMERA).build()
request.observe().subscribe { result ->
// Handle the result.
}
request.send()
To check the current permissions status without sending a request, you have two possibilities which return the same result:
// Extension on Activity.
checkPermissionsStatus(Manifest.permission.SEND_SMS, Manifest.permission.ACCESS_FINE_LOCATION)
// OR
request.checkStatus()
They will return a list of PermissionStatus
(List<PermissionStatus>
), one for each requested permission. The result list has the same size and the same order of the list of the requested permissions.
The possible statuses which can be received from these APIs are:
-
PermissionStatus.Granted
-> since API 23 the requested permission is already granted. Since API 23 the permission isn't listed in the manifest -
PermissionStatus.Denied.Permanently
-> under API 23 the permission isn't listed in the manifest. This status can't be returned since API 23 -
PermissionStatus.Denied.ShouldShowRationale
-> the requested permission is denied, but not permanently, this status can't be returned under API 23 -
PermissionStatus.RequestRequired
-> the requested permission requires a runtime request to establish its status (it can be either permanently denied or never asked). This status can't be returned under API 23
This API returns the same result of sending a permission request under API 23.
To manage the runtime permissions since Android M there are two main components:
RuntimePermissionHandlerProvider
RuntimePermissionHandler
This provider is used to provide an instance of RuntimePermissionHandler
when the request is built. The provided instance of RuntimePermissionHandler
must be available instantly.
You can cache the instance of RuntimePermissionHandler
to use it for all the requests, but you need to manage its lifecycle manually.
Used to handle the runtime permissions since Android M. This component must persist across configuration changes or save its state because the permissions request is partially handled by the OS. The entire lifecycle of the runtime permissions is specified inside this component, so, in order to implement a custom lifecycle, you need to specify a custom RuntimePermissionHandlerProvider
that will provide your custom RuntimePermissionHandler
.
This library is built also to easily inject the PermissionRequest
instances inside the components which uses them.
Example
If you use Dagger, you can provide the implementation of a PermissionRequest
and use that request inside of a presenter without relying on the Android framework.
In this way, the permissions management can be easily mocked and tested.
This library has the ability to automatically save the instance state of your permissions request and to re-attach the listeners/observers to the pending request after the state has been restored.
This can be useful, for example, in the following case:
- your Activity doesn't require any permissions by default
- the user performs an action which requires some permissions
- the permissions dialog is shown to the user
- the user puts the app in the background
- after some time the process is killed
- the user puts the app in the foreground
- the permissions dialog is still visible and the user accepts the permissions
- the action should be executed instantly after the user accepted the permissions
The only limitation to this is that you should add the listeners/observers to your PermissionRequest
in a method always invoked after the state has been restored (e.g. Activity.onCreate()
).
Your request can still be sent without any limitation in any moment you require and the attached listeners will be automatically notified when the permissions status changes.
e.g.
override fun onCreate(savedInstanceState: Bundle?) {
[...]
val request = permissionsBuilder(Manifest.permission.CAMERA).build()
request.addListener { result ->
// Handle the result.
}
button.setOnClickListener {
request.send()
}
}
By default this library uses ContextCompat
APIs to check the permissions below Android M and a Fragment
to check the runtime permissions since Android M.
The Fragment
internally uses the ActivityResultLauncher
API to request the permissions and to receive the result.
The usage of a Fragment
has not a real performance impact because:
- it's light-weight
- it hasn't no UI at all
- it's shared between permissions requests