We all know that Android Marshmallow introduced runtime permissions letting user to allow or deny any permission at runtime. Implementing runtime permissions is a tedious process and developer needs to write lot of code just to get a single permission.

In this article, we are going to simplify the process of adding the runtime permissions using Dexter library. Using this library, the permissions can be implemented in few minutes.

android-runtime-permissions-using-dexter

This is an introductory article about the Dexter covering basic features offered by the library. Dexter provides other features like using it with SnackBar, different types of listeners, error handling and few other. You can find more information on Dexter’s developer page.

1. Dexter Permissions Library

To get started with Dexter, add the dependency in your build.gradle

dependencies {
    // Dexter runtime permissions
    implementation 'com.karumi:dexter:4.2.0'
}

1.1 Requesting Single Permission

To request a single permission, you can use withPermission() method by passing the required permission. You also need a PermissionListener callback to receive the state of the permission.

> onPermissionGranted() will be called once the permission is granted.

> onPermissionDenied() will be called when the permission is denied. Here you can check whether the permission is permanently denied by using response.isPermanentlyDenied() condition.

The below code requests CAMERA permission.

Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        // permission is granted, open the camera
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        // check for permanent denial of permission
                        if (response.isPermanentlyDenied()) {
                            // navigate user to app settings
                        }
                    }

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

1.2 Requesting Multiple Permissions

To request multiple permissions at the same time, you can use withPermissions() method. Below code requests STORAGE and LOCATION permissions.

Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            // do you work now
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // permission is denied permenantly, navigate user to app settings
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                })
                .onSameThread()
                .check();

1.3 Error Handling

You can also catch any errors occurred while integrating the library using PermissionRequestErrorListener.

Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(listener)
                .withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Toast.makeText(getApplicationContext(), "Error occurred! " + error.toString(), Toast.LENGTH_SHORT).show();
                    }
                })
                .check();

Now let’s see how to use Dexter in an example project.

2. Creating New Project

1. Create a new project in Android Studio from File ⇒ New Project and select Basic Activity from templates.

2. Add Dexter dependency to your build.gradle

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    // ...

    // Dexter runtime permissions
    implementation 'com.karumi:dexter:4.2.0'
}

3. Open the layout file of your main activity (activity_main.xml and content_main.xml) and add two buttons to test different permission methods.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="info.androidhive.dexterpermissions.MainActivity"
    tools:showIn="@layout/activity_main">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:orientation="vertical"
        android:layout_centerHorizontal="true"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <Button
            android:id="@+id/btn_camera"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:text="CAMERA PERMISSION" />

        <Button
            android:id="@+id/btn_storage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="MULTIPLE PERMISSIONS" />

    </LinearLayout>
</RelativeLayout>

4. Open MainActivity.java and do the modification as shown below.

> requestStoragePermission() requests for camera permission.

> requestStoragePermission() requests multiple permissions at once.

> response.isPermanentlyDenied() and report.isAnyPermissionPermanentlyDenied() checks if the permission is denied permanently. Here we have to navigate user to app settings screen by showing a dialog.

package info.androidhive.dexterpermissions;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.Toast;

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 {

    private Button btnCamera, btnStorage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        btnCamera = findViewById(R.id.btn_camera);
        btnStorage = findViewById(R.id.btn_storage);

        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requestCameraPermission();
            }
        });

        btnStorage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requestStoragePermission();
            }
        });
    }

    /**
     * Requesting multiple permissions (storage and location) at once
     * This uses multiple permission model from dexter
     * On permanent denial opens settings dialog
     */
    private void requestStoragePermission() {
        Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            Toast.makeText(getApplicationContext(), "All permissions are granted!", Toast.LENGTH_SHORT).show();
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // show alert dialog navigating to Settings
                            showSettingsDialog();
                        }
                    }

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

    /**
     * Requesting camera permission
     * This uses single permission model from dexter
     * Once the permission granted, opens the camera
     * On permanent denial opens settings dialog
     */
    private void requestCameraPermission() {
        Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        // permission is granted
                        openCamera();
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        // check for permanent denial of permission
                        if (response.isPermanentlyDenied()) {
                            showSettingsDialog();
                        }
                    }

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

    /**
     * Showing Alert Dialog with Settings option
     * Navigates user to app settings
     * NOTE: Keep proper title and message depending on your app
     */
    private void showSettingsDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("Need Permissions");
        builder.setMessage("This app needs permission to use this feature. You can grant them in app settings.");
        builder.setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                openSettings();
            }
        });
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        builder.show();

    }

    // navigating user to app settings
    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);
    }

    private void openCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, 100);
    }
}
android-runtime-permissions-with-dexter-library
Subscribe
Notify of
guest
69 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Tigani
Tigani
2 years ago

Thanks guru ..happy new year wish you all the best

Ravi Tamada
2 years ago
Reply to  Tigani

Thank you Tigani. I wish you the same 🙂

mavilla vishnu vardhan
mavilla vishnu vardhan
2 years ago

You are really a saviour. Thanks a lot.

Ravi Tamada
2 years ago

You are welcome 🙂

Francis Ng'wandu
Francis Ng'wandu
2 years ago

Thanks for your help. I real like your tutorials

Ravi Tamada
2 years ago

Cheers!

Anushiya Anu
Anushiya Anu
2 years ago

superb bro…thank you so much…keep posting:)

Ravi Tamada
2 years ago
Reply to  Anushiya Anu

Yup I’ll do my best.

vicky
vicky
2 years ago

hello sir, Can you post some tutorial related to watermarking for types doc.

Ravi Tamada
2 years ago
Reply to  vicky

You have to use any image / document processing libraries.

vicky
vicky
2 years ago
Reply to  Ravi Tamada

No.
I find FFmpeg library but it’s very slow and also updated my APK size more than 16 MB.
Sir, Can you guide me for better options.

Ravi Tamada
2 years ago
Reply to  vicky

Try this library (I haven’t tried) https://github.com/vinaygaba/RubberStamp

For better solution, consider using ImageMagick or OpenCV.

vicky
vicky
2 years ago
Reply to  Ravi Tamada

Firstly thanks Sir, But sir this lib works only for images. Can you provides any idea or code related this functionality…….

Jankari Hindi
Jankari Hindi
2 years ago

Respected Sir Can You Tell Me Where You are Learning WordPress Website Development And Seo.Please sir Reply

Ravi Tamada
2 years ago
Reply to  Jankari Hindi

There is not just one website to learn WordPress or SEO. I can suggest you these.
https://www.shoutmeloud.com/wordpress-guide
http://www.wpbeginner.com/category/wp-tutorials/

Ziigic
Ziigic
2 years ago

Thank you, I’m waiting for this tutorial.

Ravi Tamada
2 years ago
Reply to  Ziigic

you are welcome 🙂

chandan sharma
chandan sharma
2 years ago

Hi . I want to know is there any limitation if we use dexter library instead of normal android program for run time permissions ? Someone one was telling me that use of libraries will make our project heavy so we should only use libraries if we dont have other alternative. Please tell me about this .

Ravi Tamada
2 years ago
Reply to  chandan sharma

Yes libraries makes the app size bigger but Dexter is lightweight. You need to use proper ProGuard rules to minimize the apk size while building it in release mode.
https://github.com/Karumi/Dexter/blob/master/dexter/proguard-rules.pro

Pankaj Jangid
Pankaj Jangid
2 years ago

Can It Work On Fragments ?

Ravi Tamada
2 years ago
Reply to  Pankaj Jangid

It should be.

Pawan Soni
Pawan Soni
2 years ago

Great Tutorial, but I am facing an issue like when adding more permission it denied that permission even open setting and allow permissions.

Ravi Tamada
2 years ago
Reply to  Pawan Soni

Can you post the code?

Pawan Soni
Pawan Soni
2 years ago
Reply to  Ravi Tamada

private void requestStoragePermission() {
Dexter.withActivity(this)
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.READ_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.READ_PHONE_STATE)
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
// check if all permissions are granted
if (report.areAllPermissionsGranted()) {
Toast.makeText(getApplicationContext(), “All permissions are granted!”, Toast.LENGTH_SHORT).show();
}

// check for permanent denial of any permission
if (report.isAnyPermissionPermanentlyDenied()) {
// show alert dialog navigating to Settings
showSettingsDialog();
}
}

@Override
public void onPermissionRationaleShouldBeShown(List permissions, PermissionToken token) {
token.continuePermissionRequest();
}
}).
withErrorListener(new PermissionRequestErrorListener() {
@Override
public void onError(DexterError error) {
Toast.makeText(getApplicationContext(), “Error occurred! ” + error.toString(), Toast.LENGTH_SHORT).show();
}
})
.onSameThread()
.check();
}

Pawan Soni
Pawan Soni
2 years ago
Reply to  Pawan Soni

It suggest me to open setting but in mobile setting all permission already granted.

Ravi Tamada
2 years ago
Reply to  Pawan Soni

Strange! Are these permissions added in manifest? Also check in different devices / emulators.

Pawan Soni
Pawan Soni
2 years ago
Reply to  Ravi Tamada

Yes!!! Already Added in manifest, but let it be check on other device.
and thanks again for Tutorial because Run time Permission very big deal ..

Ravi Tamada
2 years ago
Reply to  Pawan Soni

Yeah! Try Google’s EasyPermissions library too. I have to write an article on that lib too.

Pawan Soni
Pawan Soni
2 years ago
Reply to  Pawan Soni

Thank you so much.I had missed one permission in Manifest.It Working Now.
This tutorial very Helpful because Without allow All Permission You can not go ahead.
beacuse before some time It was difficult challange for me. Thanks Again

Ravi Tamada
2 years ago
Reply to  Pawan Soni

I am glad it solved. Runtime permissions are messy. The libraries are there from the beginning, I wrote the article after so much delay.

고양이는야옹야옹
고양이는야옹야옹
2 years ago

Thank you for great solution! I want share my country developer, so translate this post in my blog, is it possible?

Ravi Tamada
2 years ago

Yes you can but please mention this article somewhere in your post.

Moh Halim Bimantara
Moh Halim Bimantara
2 years ago

good

Julian
2 years ago

This looks promising. I thought about integrating something like this in my own app. Love those libraries which save you time. Going to try this out.

I think it’s important to have i.e. a settings page, where the user has an overview of the granted permissions.

Rushikesh Chaudhari
Rushikesh Chaudhari
2 years ago

can you provide the plugin like that which syntax highlighter you are using in your website for codes.?

Rushikesh Chaudhari
Rushikesh Chaudhari
2 years ago
Reply to  Ravi Tamada

and which one your are using.? I am asking because I like your theme.

Ravi Tamada
2 years ago

I am using SyntaxHighlighter. Mine is customized.

Dharmendra Mishra
Dharmendra Mishra
2 years ago

Code working fine but when we deny Permissions Dialog not showing
thank you

Gersey Zoltán
Gersey Zoltán
2 years ago

I also have the same thing.

Amanpreet Kaur
Amanpreet Kaur
2 years ago

I am also facing the same problem

@Murali
@Murali
2 years ago

Thank you so much sir,,,,,

Ravi Tamada
2 years ago
Reply to  @Murali

You are welcome 🙂

Muhammad Aamir Akhter
Muhammad Aamir Akhter
2 years ago

when i click on open setting the application crash. Please help me

Ravi Tamada
2 years ago

Check the LogCat for errors.

Sandeep Kumar
Sandeep Kumar
2 years ago

sir, this was really a great job, but i m having little problem.
I have added seven permissions
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
Manifest.permission.VIBRATE,
Manifest.permission.RECORD_AUDIO
but it ask for only two permission audio & storage and even after giving permission it show dialog to go to setting every time i open the app please help me sir

Ravi Tamada
2 years ago
Reply to  Sandeep Kumar

Request only the necessary permissions. INTERNET is not runtime permission and not needed to request it.

You can see list of dangerous permissions here.
https://developer.android.com/guide/topics/permissions/overview#permission-groups

Sandeep Kumar
Sandeep Kumar
2 years ago
Reply to  Ravi Tamada

this was really great 👏👏👏

Sandeep Kumar
Sandeep Kumar
2 years ago

(please read my previous question before reading this)
sir i used below logic to prevent app from asking permission
// check for permanent denial of any permission
if (report.isAnyPermissionPermanentlyDenied()) {

SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(“PERMISSION_PERMANENTLY_DENIED”,true);
editor.apply();

if(!sharedPref.getBoolean(“PERMISSION_PERMANENTLY_DENIED”,false)){
// show alert dialog navigating to Settings
showSettingsDialog();
}

}

should i use it? because first because at first time app shown a new type of dialog “screen overlay detected”
what would be consequences if i use above code on performance

Ravi Tamada
2 years ago
Reply to  Sandeep Kumar

Preference manager is not necessary when Dexter is used. It can handle it the first time case and denied.

Sandeep Kumar
Sandeep Kumar
2 years ago
Reply to  Ravi Tamada

sir i had tried on different devices but that not happened..that why i had to use this logic..

Rohit Singh
Rohit Singh
2 years ago

hi sir how can we handle following case in dexter :-

Step 1: Opened app and gave all the necessary permissions

Step 2: Clicked Home button(So the app is in background)

Step 3: Manually changed the permissions in the Settings

Step 4: Launched the app from multitasks, now it crashes because of app context becomes invalid

normally we use onRequestPermissionsResult. but in dexter how can we handle this ??

deepak
deepak
1 year ago
Reply to  Rohit Singh

write all permission code in onResume

Shariq Khan
Shariq Khan
2 years ago

Although i used dexter, after clicking allow , my location didnt turned on, i had to go manually to the settings and turned on my location. I am using naughat. Why is this hapening sir ?? Am i doing something wrong? Your answer would be highly appeciable 🙂 Thanks.

Hamid Liaqat
Hamid Liaqat
2 years ago

very nice sir its so easy thankio..

sir i have a little error that is
Error: The processing instruction target matching “[xX][mM][lL]” is not allowed.

Gaurav meghanathi
Gaurav meghanathi
2 years ago

Here i have use Dexter permission is granted on location update but it does not show location on lolipop with i am not able to find whether permission issue or location update call back result is not getting … If any suggestions to please help me …

Muhammad Afham
Muhammad Afham
1 year ago

Permissions at run time only appears on Marshmallow to higher versions. If you have declared permissions in manifest then on Lollipop it will automatically grant permissions while installing the app.

Chaudhary Ritesh Singh
Chaudhary Ritesh Singh
1 year ago

how can i onn my mobile data from third my app
i.e how to on mobile data programmatically

harshit yadav
harshit yadav
1 year ago

It’s nice to see a disclaimer like yours!

Ginish
Ginish
1 year ago

I got some memory leakage after integrating this..

Mariya
1 year ago

Thanks for the post…

Iroid Technologies
1 year ago

Nice post

Nguyễn Thành Minh
Nguyễn Thành Minh
10 months ago

I think you don’t need startActivityForResult(intent, 101); because you don’t handle the result

Kevin Arturo Ramirez Zavalza
Kevin Arturo Ramirez Zavalza
8 months ago

Great explanation, but I have a question, How can I update my UI after all the permissions are granted? There is any callback to listen to the result?

Ravi Tamada
8 months ago

Yes, below is callback

.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
// check if all permissions are granted
if (report.areAllPermissionsGranted()) {
// do you work now
}

Ashpaq S A
Ashpaq S A
5 months ago

Sir, Its Not working on Deny of Permission the Dialog Closes, Setting Option Is not Comming
Checked With your Apk on Redmi 7a, Redmi 4, redmi 4 A , Emulator.

Ndivho Mamathuba
Ndivho Mamathuba
4 months ago
Reply to  Ashpaq S A

I also have the issue, please update if you have found the solution

Ndivho Mamathuba
Ndivho Mamathuba
4 months ago
Reply to  Ashpaq S A

public void onPermissionDenied(PermissionDeniedResponse response)
{showSettingsDialog();}

Remove the if-statement, the permission was already denied.

Abhishek Abhi
5 months ago

Recommended artice

69
0
Would love your thoughts, please comment.x
()
x