Skip to main content

How to Request Multiple Runtime Permissions in Android Using Activity Result API

How to Request Multiple Runtime Permissions in Android Using Activity Result API
How to Request Multiple Runtime Permissions in Android Using Activity Result API

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_STORAGE is 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!

Comments

  1. 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.
    Contact 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/

    ReplyDelete

Post a Comment

Popular posts from this blog

How to Download Apk file from Url and Install Programmatically

In this post we learn about download apk file from server or website and then install it Programmatically in Phone. Sometimes we have to download external apk file from server and then install if downloading successfully finished.For this we use AsyncTask class  for background process. So here is Code Snippet for this task.Lets Start :- Before this we have to add these Permissions in Manifest.xml file : <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> DownloadNewVersion.java class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> { @Override protected void onPreExecute() { super.onPreExecute(); bar = new ProgressDialog(getActivity()); bar.setCancelable(false); bar.setMessage("Downl...

Working with Android 11 (Changes and Security Features)

 Hello everyone , I am here with new article which is hot topic nowadays "Android 11" .The stable version of Android.  Android 11 is the eleventh major release and 18th version of Android, the mobile operating system developed by the Open Handset Alliance led by Google. It was released on September 8, 2020.It is comes with many security features and other features as well . And it is now compulsory in play store  to upload new apps with API lavel 30 which is compatible with Android 11 and from November onwards old apps also have to update with API 30 .Some other guidelines you can check out from here . Play Store Guidelines So its clear that we have to update our apps with API level 30 .But Android 11 comes with some changes as well which we have to do in our projects. For example from Android developer site "Android 11 (API level 30) further enhances the platform, giving better protection to app and user data on external storage. ". Scoped storage enforcement: Apps...

How to sort a list in ascending order and Add header by the first letter in the RecyclerView in Android

Hello Forks ! Hope you are doing well. In this tutorial we will understand how to sort a list of data, it could be any data like bank names , places names etc. in ascending order with a header which grouped the same type of data under it. For example we have a list of banks data and we want to group all banks starting with 'A' character in single unit and so on. So without taking too much time  let's move to the coding part and understand how we can achieve this. Step 1 : Create a Model class Named Bank.java public class Bank { private String name; public Bank (String name) { this .name = name; } public String getName () { return name; } } Step 2 : Sort the List of Banks with this Method import java.util.Collections; import java.util.Comparator; import java.util.List; public void sortBankList (List<Bank> bankList) { Collections.sort(bankList, new Comparator <Bank>() { @Override pub...