Make android runtime permissions easier with dexter cover

In Android Marshmallow Google introduced new permissions system - now we request permissions in runtime. This approach is safer for the user, but for developers it is more code to write. We need to check if user willingly grants access and, if not, ask for it. Of course, old <uses-permission> in app manifest stays the same as before. Now there are two places serving nearly the same purpose. Next, call requestPermission() method (it’s required in our Activity class) and write callback with the results. Don’t forget about request code, same for defined methods! What if out app requires a really big amount of permissions? Activities can be overloaded with that logic and this causes a mess. Don’t worry - community comes with help. 

Dexter is Apache licensed library that helps you keep order in the code - it simplifies the process of granting permissions and frees your activities - you can write those methods where you want and separate them from your business logic. But remember - it can’t handle non-existing permissions! For API version earlier than 16 always check Android version and use ContextCompat for checking permissions!

Installation

Just add this line to your build.gradle file to dependencies block:

compile ‚com.karumi:dexter:4.1.0’

Preparations

Go to your valid activity and call (of course, instead of my permission add yours):

        Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(listener)
                .check();

Dexter offers support for single and multiple permissions. For single permission just implement PermissionListener:

PermissionListener listener = new PermissionListener() {
        @Override
        public void onPermissionGranted(PermissionGrantedResponse response) {

        }

        @Override
        public void onPermissionDenied(PermissionDeniedResponse response) {

        }

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

In that listener, you can handle events that you need. Method onPermissionRationaleShouldBeShown() should be called when you need additional explanation about requested permission. Remember - when the token is used, you can’t call Dexter again. That is an example implementation of that method.

If you want to use Snackbar or Dialog to show errors for the user, Dexter has appropriate methods for you.

PermissionListener dialogPermissionListener =
                DialogOnDeniedPermissionListener.Builder
                        .withContext(this)
                        .withTitle("Camera permission")
                        .withMessage("Camera permissions please")
                        .withButtonText(android.R.string.ok)
                        .withIcon(R.mipmap.ic_launcher)
                        .build();

DialogOnDeniedPermissionListener builds simple dialog, where you can inform the user about required permission if they reject your request. SnackbarOnDeniedPermissionListener shows the Snackbar in a similar situation, but offers callback events too (when Snackbar is showing or dismissed):

 PermissionListener snackbarPermissionListener =
                SnackbarOnDeniedPermissionListener.Builder
                        .with(, "Camera access is needed to take pictures of your dog")
                        .withOpenSettingsButton("Settings")
                        .withCallback(new Snackbar.Callback() {
                            @Override
                            public void onShown(Snackbar snackbar) {
                            }
                            @Override
                            public void onDismissed(Snackbar snackbar, int event) {
                            }
                        }).build();

If you want, you can compound your listeners into one - use CompositePermissionListener, for example:

PermissionListener compositePermissionListener = new CompositePermissionListener(snackbarListener, dialogListener);

Dexter also offers straightforward error handling - if you want to display debug errors, setting ErrorListener should be enough:

Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.WRITE_CALENDAR,
                        Manifest.permission.WRITE_CONTACTS,
                        Manifest.permission.WRITE_SETTINGS
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
            }

            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
            }
            }).withErrorListener(new PermissionRequestErrorListener() {
            
            @Override
            public void onError(DexterError error) {
                Log.e(TAG, error.toString());
            }
            
        }).check();

Now you should be able to solve single permissions problem. But what about multiple permissions? The greatest magic is here:

        Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.WRITE_CALENDAR,
                        Manifest.permission.WRITE_CONTACTS,
                        Manifest.permission.WRITE_SETTINGS
                ).withListener(new MultiplePermissionsListener() {
            @Override public void onPermissionsChecked(MultiplePermissionsReport report) {}
            @Override public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {}
        }).check();

You can also use MultiplePermissionsReport object for getting all denied or granted permissions. This will make it easier - calling areAllPermissionsGranted(), isAnyPermissionPermanentlyDenied() in many cases should be enough. 

If you deny any of multiple permission and request it again, you will get only requests that you do not have. If you deny permanently one of them it will not show at all. In that case, you will need to re-enable it in app settings.

First and most useful advice when you are using this library is: do not call Dexter from the noHistory activity. When requesting permissions Dexter creates its own activity and dismisses original one.


 

Post tags:

Join our awesome team
Check offers

Work
with us

Tell us about your idea
and we will find a way
to make it happen.

Get estimate