Last active
March 18, 2024 15:36
-
-
Save marcellogalhardo/bbf43cf43a0eef980442ffde10ae2e54 to your computer and use it in GitHub Desktop.
A abstraction to handle permissions in a Compose-way.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.Activity | |
import android.content.pm.PackageManager | |
import androidx.activity.compose.rememberLauncherForActivityResult | |
import androidx.activity.result.ActivityResultLauncher | |
import androidx.activity.result.contract.ActivityResultContracts | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.platform.LocalConfiguration | |
import androidx.core.app.ActivityCompat | |
import androidx.core.content.ContextCompat | |
internal interface PermissionState { | |
val status: Status | |
fun requestPermission() | |
enum class Status { Granted, Denied, ShowRationale, NeverAskAgain } | |
} | |
internal fun PermissionState.shouldRequestPermission(): Boolean { | |
return status != Status.Granted && status != Status.NeverAskAgain | |
} | |
private class PermissionStateImpl( | |
private val activity: Activity, | |
private val permission: String, | |
) : PermissionState { | |
override var status: Status by mutableStateOf( | |
getPermissionStatus(isRequestPermissionsResult = false) | |
) | |
fun onResult() { | |
status = getPermissionStatus(isRequestPermissionsResult = true) | |
} | |
var launcher: ActivityResultLauncher<String>? = null | |
override fun requestPermission() { | |
launcher?.launch(permission) | |
} | |
private fun getPermissionStatus( | |
isRequestPermissionsResult: Boolean, | |
): Status = with(activity) { | |
when { | |
isPermissionGranted(permission) -> Status.Granted | |
shouldShowRationale(permission) -> Status.ShowRationale | |
isRequestPermissionsResult -> Status.NeverAskAgain | |
else -> Status.Denied | |
} | |
} | |
} | |
private fun Activity.isPermissionGranted(permission: String): Boolean { | |
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED | |
} | |
private fun Activity.shouldShowRationale(permission: String): Boolean { | |
return ActivityCompat.shouldShowRequestPermissionRationale(this, permission) | |
} | |
@Composable | |
internal fun rememberPermissionState( | |
permission: String, | |
): PermissionState { | |
val activity = LocalActivity.current | |
val handler = remember(LocalConfiguration.current) { PermissionStateImpl(activity, permission) } | |
handler.launcher = rememberLauncherForActivityResult( | |
contract = ActivityResultContracts.RequestPermission(), | |
onResult = { handler.onResult() }, | |
) | |
return handler | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment