Jetpack Compose Check Permission (Accompanist)

November 7, 2021

Use Accompanist - Permissions

Dependecies

dependencies {
    implementation "com.google.accompanist:accompanist-permissions:0.20.0"
}

Check for Read External Storage Permission

Edit AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application ...>

    </application>
</manifest>

Check Permission Composable

@ExperimentalPermissionsApi
@Composable
fun RequireExternalStoragePermission(
    navigateToSettingsScreen: () -> Unit,
    content: @Composable() () -> Unit
) {
    // Track if the user doesn't want to see the rationale any more.
    var doNotShowRationale by rememberSaveable { mutableStateOf(false) }

    // Permission state
    val permissionState = rememberPermissionState(
        android.Manifest.permission.READ_EXTERNAL_STORAGE
    )

    when {
        // If the camera permission is granted, then show screen with the feature enabled
        permissionState.hasPermission -> {
            content()
        }
        // If the user denied the permission but a rationale should be shown, or the user sees
        // the permission for the first time, explain why the feature is needed by the app and allow
        // the user to be presented with the permission again or to not see the rationale any more.
        permissionState.shouldShowRationale ||
                !permissionState.permissionRequested -> {
            if (doNotShowRationale) {
                Text("Feature not available")
            } else {
                Column {
                    Text("Need to read external storage to import photos. Please grant the permission.")
                    Spacer(modifier = Modifier.height(8.dp))
                    Row {
                        Button(onClick = { permissionState.launchPermissionRequest() }) {
                            Text("Request permission")
                        }
                        Spacer(Modifier.width(8.dp))
                        Button(onClick = { doNotShowRationale = true }) {
                            Text("Don't show rationale again")
                        }
                    }
                }
            }
        }
        // If the criteria above hasn't been met, the user denied the permission. Let's present
        // the user with a FAQ in case they want to know more and send them to the Settings screen
        // to enable it the future there if they want to.
        else -> {
            Column {
                Text(
                    "External storage permission denied. " +
                            "Need to read external storage to import photos. " +
                            "Please grant access on the Settings screen."
                )
                Spacer(modifier = Modifier.height(8.dp))
                Button(onClick = navigateToSettingsScreen) {
                    Text("Open Settings")
                }
            }
        }
    }
}

Show Composable only when permission granted, else ask for permission.

@ExperimentalPermissionsApi
@Composable
fun ImportPhotoScreen() {
    val context = LocalContext.current
    RequireExternalStoragePermission(navigateToSettingsScreen = {
        context.startActivity(
            Intent(
                Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                Uri.fromParts("package", context.packageName, null)
            )
        )
    }) {

        // Show Albums
        Albums()
    }

}

Request Multiple Permissions

Edit AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>

    <application ...>

    </application>
</manifest>

Replace the following

/*
val permissionState = rememberPermissionState(
    android.Manifest.permission.READ_EXTERNAL_STORAGE
)
 */

val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    listOf(
        android.Manifest.permission.READ_EXTERNAL_STORAGE,
        android.Manifest.permission.ACCESS_MEDIA_LOCATION
    )
} else {
    listOf(
        android.Manifest.permission.READ_EXTERNAL_STORAGE,
    )
}

val permissionState = rememberMultiplePermissionsState(permissions)
// Button(onClick = { permissionState.launchPermissionRequest() })
Button(onClick = { permissionState.launchMultiplePermissionRequest() })
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.