In this blog, we are learning that the ‘Downgradable permissions’ in Android apps. You can disable runtime permissions that your app no longer needs on Android 13 (API level 33) and higher. Perform this action when you update your app so that users are more likely to comprehend why your program keeps asking for particular permissions.
Use the command revokeSelfPermissionOnKill(String) to revoke ONE privilege.
Use revokeSelfPermissionsOnKill(Collection) to revoke MULTIPLE permissions.
Next, in our AndroidManifest.xml file, we must define a few runtime permissions. In our app, these permissions will be requested at runtime. We will use the MANAGE_EXTERNAL_STORAGE and ACCESS_FINE_LOCATION permissions in this post.
1 2 3 4 5 |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
We have added these run time permission in the manifest file, now we are creating the XML layout to show the button to Permission GRANT or REVOKE.
XML layout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <androidx.appcompat.widget.AppCompatButton android:id="@+id/button_request_permission" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Request Permissions" /> <androidx.appcompat.widget.AppCompatButton android:id="@+id/button_revoke_all_permissions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Revoke All Permissions" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="200dp" android:gravity="center" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <androidx.appcompat.widget.AppCompatButton android:id="@+id/button_revoke_location_permission" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Revoke Location Permission" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <androidx.appcompat.widget.AppCompatButton android:id="@+id/button_revoke_storage_permission" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Revoke Storage Permission" /> </LinearLayout> <TextView android:id="@+id/text_call_permission" style="@style/TextAppearance.MaterialComponents.Body1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="GRANTED" /> </LinearLayout> </androidx.appcompat.widget.LinearLayoutCompat> |
In this code, we are seeing, we have created two buttons first one to give all required permissions, and the second one is to revoke all given permissions.
MainActivity.kt
file.
We are creating a permissions list.
1 |
val requiredPermissions = <em>arrayOf</em>(<br> Manifest.permission.<em>CAMERA</em>,<br> Manifest.permission.<em>ACCESS_FINE_LOCATION</em>,<br>) |
now we are declaring the permission request code and the revoke code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
private fun initializationView() { mContentBinding.buttonRequestPermission.setOnClickListener { if (requiredPermissions.all { permissionGranted(it) }) { updateMainUI() } else { requestPermissionsLauncher.launch(requiredPermissions) } } mContentBinding.buttonRevokeLocationPermission.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { revokeSelfPermissionOnKill(Manifest.permission.ACCESS_FINE_LOCATION) Toast.makeText(this,"Permission has been revoked please re-start your app",Toast.LENGTH_SHORT).show() } } mContentBinding.buttonRevokeStoragePermission.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { revokeSelfPermissionOnKill(Manifest.permission.CAMERA) Toast.makeText(this,"Permission has been revoked please re-start your app",Toast.LENGTH_SHORT).show() } } mContentBinding.buttonRevokeAllPermissions.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { revokeSelfPermissionsOnKill(requiredPermissions.toList()) Toast.makeText(this,"Permission has been revoked please re-start your app",Toast.LENGTH_SHORT).show() } } } |
Remember that the permissions that have been revoked MUST BE GRANTED FIRST! The methods will throw an Exception if not.
Conclusion
Congratulations!! 🤩 You have mastered the Android 13 Downgradable Permissions.
Visit the link for additional information on the Downgradable Permissions in Android 13.
Thanks for reading this blog. You can also check other blogs from here for more knowledge.
Always be ready for learning 🙂