« Jetpack Compose Runtime Permissions
What is Runtime Permission?
Before Marshmallow (Android 6.0), permissions were handled at install-time and specified in the AndroidManifest.xml within the project. After Marshmallow, permissions must now be requested at runtime before being used. Runtime permissions prevent apps from gaining access to private data without a user’s consent and provide them with additional context and visibility into the types of permissions that applications are either seeking or have been granted.
We will use Google’s accompanist libraries for this
First of all, we need to add some dependency for Runtime Permission:
1dependencies {2 implementation "com.google.accompanist:accompanist-permissions:0.24.3-alpha"3}
Now we need to add the permissions in our AndroidManifest.xml file:
1<?xml version="1.0" encoding="utf-8"?>2<manifest xmlns:android="http://schemas.android.com/apk/res/android"3 package="com.erselankhan.compose">45 <uses-permission android:name="android.permission.CAMERA"/>6 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>7 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>89 <application10 android:allowBackup="true"11 android:icon="@mipmap/ic_launcher"12 android:label="@string/app_name"13 android:roundIcon="@mipmap/ic_launcher_round"14 android:supportsRtl="true"15 android:theme="@style/Theme.Compose">16 <activity17 android:name=".MainActivity"18 android:exported="true"19 android:label="@string/app_name"20 android:theme="@style/Theme.Compose">21 <intent-filter>22 <action android:name="android.intent.action.MAIN" />2324 <category android:name="android.intent.category.LAUNCHER" />25 </intent-filter>26 </activity>2728 <meta-data29 android:name="com.google.android.geo.API_KEY"30 android:value="AIza***************************"/>3132 </application>3334</manifest>
There are two types of permissions states in Jetpack Compose:
- Single Permission State
- Multiple Permissions State
Single Permission State:
We will use rememberPermissionState function for a single permission state. This function takes two parameters, the first parameter is for the permission name and the second parameter is for the permission state i.e it is granted or not.
Multiple Permissions State:
We will use rememberMultiplePermissionsState function for multiple permissions state. This function takes two parameters, the first parameter is for the list of permissions names and the second parameter is for the permission states of all the requested permissions.
1val singlePermissionState = rememberPermissionState(2 Manifest.permission.CAMERA3) { isGranted ->4 if (isGranted) {5 Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()6 } else {7 Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()8 }9}1011val multiplePermissionsState = rememberMultiplePermissionsState(12 permissions = listOf(13 Manifest.permission.WRITE_EXTERNAL_STORAGE,14 Manifest.permission.READ_EXTERNAL_STORAGE15 )16) { permissionStateMap ->17 if (!permissionStateMap.containsValue(false)) {18 Toast.makeText(context, "Permissions Granted", Toast.LENGTH_SHORT).show()19 } else {20 Toast.makeText(context, "Permissions Denied", Toast.LENGTH_SHORT).show()21 }22}
We are just initializing the single and multiple permissions states. We are taking Camera permission by using a single permission state, and taking Read Storage and Write Storage permissions by using multiple permissions states.
Let’s invoke launchPermissionRequest and launchMultiplePermissionRequest functions to take these permissions:
1Column(2 modifier = Modifier.fillMaxSize(),3 horizontalAlignment = Alignment.CenterHorizontally,4 verticalArrangement = Arrangement.Center5) {6 Button(onClick = {7 singlePermissionState.launchPermissionRequest()8 }) {9 Text(text = "For Camera Permission")10 }11 Button(onClick = {12 multiplePermissionsState.launchMultiplePermissionRequest()13 }) {14 Text(text = "For Storage Permission")15 }16}
Here is the full code:
1@OptIn(ExperimentalPermissionsApi::class)2@Composable3fun RuntimePermissionScreen(45) {67 val context = LocalContext.current8 val singlePermissionState = rememberPermissionState(9 Manifest.permission.CAMERA10 ) { isGranted ->11 if (isGranted) {12 Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()13 } else {14 Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()15 }16 }1718 val multiplePermissionsState = rememberMultiplePermissionsState(19 permissions = listOf(20 Manifest.permission.WRITE_EXTERNAL_STORAGE,21 Manifest.permission.READ_EXTERNAL_STORAGE22 )23 ) { permissionStateMap ->24 if (!permissionStateMap.containsValue(false)) {25 Toast.makeText(context, "Permissions Granted", Toast.LENGTH_SHORT).show()26 } else {27 Toast.makeText(context, "Permissions Denied", Toast.LENGTH_SHORT).show()28 }29 }3031 Column(32 modifier = Modifier.fillMaxSize(),33 horizontalAlignment = Alignment.CenterHorizontally,34 verticalArrangement = Arrangement.Center35 ) {36 Button(onClick = {37 singlePermissionState.launchPermissionRequest()38 }) {39 Text(text = "For Camera Permission")40 }41 Button(onClick = {42 multiplePermissionsState.launchMultiplePermissionRequest()43 }) {44 Text(text = "For Storage Permission")45 }46 }47}
For full working code please visit
https://github.com/anishakd4/JetpackComposeRuntimePermissions