Use LiveData to determine the status of any permission (in the sample code below: the location permission). If the user grants the permission at any point, then we will get notified.
enum class LocationPermissionStatus {
GRANTED,
DENIED
}
class LocationPermissionStatusLiveData(
private val context: Context,
private val permissionsToListen: Array<String>
) : LiveData<LocationPermissionStatus>() {
override fun onActive() = setPermissionStatus()
fun setPermissionStatus() {
val isPermissionGranted = permissionsToListen.all {
ActivityCompat.checkSelfPermission(
context,
it
) == PackageManager.PERMISSION_GRANTED
}
if (isPermissionGranted)
postValue(LocationPermissionStatus.GRANTED)
else
postValue(LocationPermissionStatus.DENIED)
}
}
Usage
Sample usage:
viewModel.locationPermissionStatus.observe(viewLifecycleOwner, Observer { status ->
if (status != LocationPermissionStatus.GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
activity as Activity,
Manifest.permission.ACCESS_FINE_LOCATION
)
|| ActivityCompat.shouldShowRequestPermissionRationale(
activity as Activity,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
) {
// show a dialog explaining why we need the location permission
// if the user has selected in the past the "never show again"
// we need to open the system's App Settings
showPermissionsExplanation(true)
} else {
val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
} else {
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
}
requestPermissions(permissions, PERMISSION_REQUEST_CODE)
}
} else {
// Start location updates
}
})
private fun showPermissionsExplanation(openSystemAppInfo: Boolean) {
var listener: DialogInterface.OnClickListener? = null
if (openSystemAppInfo) {
listener = DialogInterface.OnClickListener { _, _ ->
// will be executed if user clicks OK button
startAppSettingsConfigActivity()
}
}
context.let {
AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.permission_required))
.setPositiveButton(getString(R.string.label_Ok), listener)
.create()
.show()
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />