
How to Request Multiple Runtime Permissions in Android Using Activity Result API
In modern Android development, handling runtime permissions gracefully is crucial for creating smooth and secure user experiences. Since Android 6.0 (Marshmallow), requesting runtime permissions has become a standard practice to ensure users understand the access requirements of your app. However, managing multiple permissions simultaneously can get tricky if not done correctly.
With the introduction of the Activity Result API in AndroidX, developers now have a cleaner, more robust way to request permissions and handle their results. This post will guide you through the process of requesting multiple runtime permissions using the Activity Result API with practical Kotlin examples, best practices, and detailed explanations.
Why Use the Activity Result API for Permissions?
Prior to the Activity Result API, permission requests were generally handled using ActivityCompat.requestPermissions() and processed in onRequestPermissionsResult(). This approach could be verbose and imposed tight coupling between permission requests and handling logic. Mismanaging these callbacks often led to bugs and repetitive code.
The Activity Result API solves these problems by providing a lifecycle-aware and type-safe way to register and handle permission requests via callback lambdas. It dramatically simplifies permission management and improves code readability.
Benefits at a glance:
- Clean separation of permission request and response handling
- Better lifecycle integration—automatic cleanup and no leaks
- Supports both single and multiple permission requests effortlessly
- Improved readability and maintainability
Step-by-Step: Requesting Multiple Permissions Using Activity Result API
Let's walk through a practical example of requesting two common Android permissions: CAMERA and WRITE_EXTERNAL_STORAGE (or READ_EXTERNAL_STORAGE depending on your use case).
1. Add Permissions to AndroidManifest.xml
First, declare the permissions you need in your project's manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissiondemo">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
... >
...
</application>
</manifest>
2. Setup the Activity Result Launcher
Inside your Activity or Fragment, declare a launcher that uses the ActivityResultContracts.RequestMultiplePermissions contract.
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions: Map<String, Boolean> ->
// Handle permission results here
permissions.entries.forEach { permission ->
if (permission.value) {
// Permission granted
Log.d("Permissions", "${permission.key} granted")
} else {
// Permission denied
Log.d("Permissions", "${permission.key} denied")
}
}
}
This launcher is a lifecycle-aware object. When invoked, it will prompt the user with the permissions dialog and return the results asynchronously in the lambda.
3. Request Permissions When Needed
Next, call the launcher method to request multiple permissions. It’s good practice to check if permissions are already granted before requesting them again, improving UX by avoiding unnecessary dialogs.
private fun checkAndRequestPermissions() {
val permissionsToRequest = mutableListOf<String>()
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.CAMERA)
}
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (permissionsToRequest.isNotEmpty()) {
// Launch the permission request dialog
requestPermissionLauncher.launch(permissionsToRequest.toTypedArray())
} else {
// All permissions are already granted
proceedWithAppLogic()
}
}
private fun proceedWithAppLogic() {
// Your code after permissions are approved
Toast.makeText(this, "All permissions granted!", Toast.LENGTH_SHORT).show()
}
4. Handle User’s Permission Response
In the callback lambda provided to registerForActivityResult, you already have access to a Map<String, Boolean>, where the key is the permission name and the value indicates whether the permission was granted.
Use this information to control the flow of your app accordingly — you can show rationale dialogs, explain why some features won't work, or direct users to app settings for manually enabling permissions if needed.
Complete Example in One Activity
Here’s a concise full example incorporating everything above:
class MainActivity : AppCompatActivity() {
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions: Map<String, Boolean> ->
var allGranted = true
permissions.entries.forEach { permission ->
if (permission.value) {
Log.d("Permissions", "${permission.key} granted")
} else {
Log.d("Permissions", "${permission.key} denied")
allGranted = false
}
}
if (allGranted) {
proceedWithAppLogic()
} else {
Toast.makeText(this, "Please grant all permissions to continue", Toast.LENGTH_LONG).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
checkAndRequestPermissions()
}
private fun checkAndRequestPermissions() {
val permissionsToRequest = mutableListOf<String>()
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.CAMERA)
}
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (permissionsToRequest.isNotEmpty()) {
requestPermissionLauncher.launch(permissionsToRequest.toTypedArray())
} else {
proceedWithAppLogic()
}
}
private fun proceedWithAppLogic() {
Toast.makeText(this, "All permissions granted!", Toast.LENGTH_SHORT).show()
// Your app logic here that requires the granted permissions
}
}
Best Practices When Requesting Permissions
- Explain Why Permissions Are Needed: Use rationale dialogs (
shouldShowRequestPermissionRationale()) before requesting permissions to inform users about the necessity. - Request Permissions At the Right Time: Don’t ask for all permissions on app launch. Request them contextually when the feature requiring them is triggered.
- Handle Denials Gracefully: Detect when users permanently deny permissions and guide them to app settings to manually enable them.
- Use Scoped Storage: For storage permissions, consider scoped storage alternatives where possible, because
WRITE_EXTERNAL_STORAGEis considered sensitive and might be restricted on newer Android versions.
Conclusion
Mastering runtime permission management is fundamental to building trustworthy and user-friendly Android apps. The Activity Result API revolutionizes how we request multiple permissions by providing a clean, concise, and lifecycle-aware approach. Using this API not only reduces boilerplate but also improves app stability and developer productivity.
In this guide, we demonstrated how to request multiple permissions simultaneously, check existing permission statuses, and handle user responses efficiently in Kotlin. Implementing these patterns in your apps will enhance both user experience and code maintainability.
Stay up-to-date with the latest Android development tools and APIs, and always respect users’ privacy and security by requesting only the permissions necessary for your app’s core features.
If you found this guide useful, share it with fellow developers! Happy coding!
Forex trading companies in India provide traders with access to currency markets through advanced platforms, trading tools, and market insights. Choosing the right Forex trading company is important for a secure and efficient trading experience. Leading companies focus on offering competitive pricing, reliable execution, user-friendly platforms, educational resources, and customer support to help traders make informed decisions. Whether you are a beginner exploring Forex markets or an experienced trader looking for advanced solutions, a trusted Forex trading company can provide the technology and resources needed to develop effective trading strategies and manage trades with confidence.
ReplyDeleteContact us Address — 1st Floor, The Sotheby Building, Rodney Bay, Gros-Islet, SAINT Lucia P.O Box 838, Castries, Saint Lucia Phone no — +97144471894 Website — https://winprofx.org/