Monitor permission status

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