Android Runtime Permissions with Dexter Library - Android Hire
Android Phones

Android Runtime Permissions with Dexter Library

Vidhi Markhedkar
Handling runtime permissions in Android can be a cumbersome task, especially with the introduction of runtime permission requests in Android Marshmallow (API level 23).

The Dexter library simplifies this process by providing an easy-to-use API for managing permissions.

In this tutorial, we'll walk you through the implementation of Dexter to handle both single and multiple permissions in your Android app.

Why Use the Dexter Library?

In Android Marshmallow, users are prompted to grant permissions at runtime rather than at the time of app installation. While this is a great step forward in terms of user privacy, it requires developers to write additional code to handle permission requests and responses. Dexter streamlines this process, allowing you to request permissions with minimal code, while also handling edge cases like permanent denial of permissions.

Step-by-Step Implementation of Dexter Library

1. Add Dexter to Your Project

First, you need to add the Dexter library to your project. Open your build.gradle (Module: app) file and add the following dependency:

implementation 'com.karumi:dexter:5.0.0'

Sync your project to ensure the library is properly added.

2. Declare Permissions in the Android Manifest

Next, declare the permissions your app needs in the AndroidManifest.xml file. For example:

" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE" />

This step is crucial as it lets the Android system know about the permissions your app will request at runtime.

3. Create the Layout File

Create an XML layout file that defines the user interface for requesting permissions. Here’s a simple example:

This layout includes two buttons: one for requesting a single permission and another for multiple permissions.

4. Implementing Permission Requests in Java (MainActivity.java)

Now, let's implement the logic to request permissions using Dexter in your MainActivity.java file.

permissions, PermissionToken token) { token.continuePermissionRequest(); } }) .withErrorListener(new PermissionRequestErrorListener() { @Override public void onError(DexterError error) { Toast.makeText(MainActivity.this, "Error occurred: " + error.toString(), Toast.LENGTH_SHORT).show(); } }) .onSameThread() .check(); } private void showSettingsDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("Permissions Required") .setMessage("This app requires permissions to function properly. You can grant them in the app settings.") .setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); openSettings(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }) .show(); } private void openSettings() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, 101); } } " style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button">
package com.example.dexterlibrary;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import com.karumi.dexter.listener.single.PermissionListener;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void requestSinglePermission(View view) {
        Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        Toast.makeText(MainActivity.this, "Camera permission granted", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        if (response.isPermanentlyDenied()) {
                            showSettingsDialog();
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).check();
    }

    public void requestMultiplePermissions(View view) {
        Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_CONTACTS,
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.CALL_PHONE,
                        Manifest.permission.CAMERA)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        if (report.areAllPermissionsGranted()) {
                            Toast.makeText(MainActivity.this, "All permissions granted!", Toast.LENGTH_SHORT).show();
                        }

                        if (report.isAnyPermissionPermanentlyDenied()) {
                            showSettingsDialog();
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                })
                .withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Toast.makeText(MainActivity.this, "Error occurred: " + error.toString(), Toast.LENGTH_SHORT).show();
                    }
                })
                .onSameThread()
                .check();
    }

    private void showSettingsDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("Permissions Required")
                .setMessage("This app requires permissions to function properly. You can grant them in the app settings.")
                .setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                        openSettings();
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                })
                .show();
    }

    private void openSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, 101);
    }
}

4.1 Granting Single Permission

The requestSinglePermission() method handles the request for a single permission, such as accessing the camera. If the permission is granted, a toast message is displayed. If denied, it checks if the permission is permanently denied and prompts the user to enable it in the app settings.

4.2 Granting Multiple Permissions

The requestMultiplePermissions() method allows you to request multiple permissions simultaneously. Dexter will handle the logic to check if all permissions are granted or if any are permanently denied. Similar to the single permission method, it provides feedback to the user through toast messages and dialogs.

Why Choose Dexter Over Native Methods?

Dexter offers a more streamlined and less error-prone approach compared to manually handling permissions. It abstracts much of the boilerplate code required when managing permissions natively, making your codebase cleaner and easier to maintain. Additionally, Dexter provides robust handling for scenarios such as permanent denial of permissions, offering a smoother user experience.

Common Issues and Troubleshooting

  • Handling Permanent Denials: If a user permanently denies a permission, it's crucial to guide them to the app settings to manually enable it. Dexter helps manage this scenario through the showSettingsDialog() method.
  • Error Handling: Dexter includes a listener for errors (PermissionRequestErrorListener), ensuring that your app can gracefully handle unexpected issues during the permission request process.

Conclusion

The Dexter library is an excellent tool for simplifying the management of runtime permissions in Android. By integrating Dexter into your app, you can reduce the amount of code needed to handle permissions and ensure a smoother, more user-friendly experience.

If you’re dealing with runtime permissions in your Android project, give Dexter a try. It’s easy to implement, reduces boilerplate code, and provides a consistent way to handle permissions across different Android versions.

Vidhi Markhedkar's profile picture

Vidhi Markhedkar

Android developer and writer with a passion for creating innovative and user-friendly apps.

Related Posts

7 Top Samsung Galaxy Ring Alternatives for 2025

7 Top Samsung Galaxy Ring Alternatives for 2025

Tired of waiting for the Samsung Galaxy Ring to hit the market? You’re not alone. While the buzz around Samsung’s smart ring continues, a plethora of impressive alternatives is already available. These devices deliver advanced health tracking, stylish designs, and unique features that cater to various lifestyles. The current lineup of smart rings caters to […]

What Is Quiet Mode on Instagram and How to Activate It

What Is Quiet Mode on Instagram and How to Activate It

Ever wondered what Quiet Mode on Instagram is all about? This simple yet powerful Instagram feature helps you take a break from the constant buzz of notifications and focus on what truly matters. Whether you’re striving for better work-life balance, dedicating time to studying, or simply trying to disconnect from social media distractions, Quiet Mode […]

How to Make a Bed in Minecraft (Step-by-Step Guide)

How to Make a Bed in Minecraft (Step-by-Step Guide)

A bed in Minecraft is very important. It lets you skip the night and set your spawn point, so if you die, you will return to your bed instead of the original world spawn. This guide will show you how to gather materials, craft a bed, and set your spawn point. We’ll also show you how to customize your bed, build bunk […]

10 Best MMORPG Games For Android

10 Best MMORPG Games For Android

Not too long ago, MMORPG games and powerful gaming consoles were mostly exclusive to PCs. They required high-end graphics and systems to deliver their immersive gameplay. But times have changed. With the rise of gaming-oriented smartphones, you can now enjoy PC-like gaming experiences on your Android device. Thanks to these technological advancements and faster internet […]

Roblox: Fruit Battlegrounds codes (January 2025)

Roblox: Fruit Battlegrounds codes (January 2025)

Fruit Battlegrounds codes are all about getting more gems and help you to shoot up your rank in this One Piece anime-inspired game. This Fruit Battlegrounds was made by Popo developer. It is an action-packed game where players battle it out using unique fruit-based abilities. With constant updates, new fruits, and exciting challenges, it’s a fruity frenzy you won’t […]

Roblox: Ultimate Football Codes (January 2025)

Roblox: Ultimate Football Codes (January 2025)

Want to get some extra items for Ultimate Football in Roblox? You’ve come to the right place! Here’s the latest list of codes to help you score touchdowns and look stylish on the field. These codes offer free rewards such as coins and cosmetics to enhance your gameplay. What are Ultimate Football Codes? Ultimate Football […]

Roblox: Da Hood Codes (January 2025)

Roblox: Da Hood Codes (January 2025)

Are you a fan of Roblox games, in this article we will look at the Roblox Da Hood Codes for December 2024 that will help you unlock exclusive items, improve your gameplay and dominate the streets of Da Hood. You can feel that the game is inspired by the Grand Theft Auto series and there […]