Tutorial

Android Runtime Permissions Example

Published on August 3, 2022
author

Anupam Chugh

Android Runtime Permissions Example

Welcome to android runtime permissions example. With the introduction of Android 6.0 Marshmallow, Google has changed the way permissions are handled by the app. In this tutorial we’ll look into the new android runtime permissions that are introduced and how to handle them. If not handled properly, it can cause application crashes.

What are Android Runtime Permissions?

With the introduction of Android 6.0 (SDK 23), users are prompted for some specific permissions at runtime when they become necessary to use. So the first question that comes to our mind is - Will the older apps run on Android Marshmallow? The answer is yes if the targetSdkVersion is 22 or less. Thus android runtime permissions support backward compatibility. Now this doesn’t mean that we can work with old model of permissions by setting the sdk version to 22. A user using Marshmallow can revoke the dangerous permissions (we’ll discuss the dangerous and normal permissions later) from the Settings->Apps->Permissions. In the case we try to call some function that requires a permission which user has not granted yet, the function will suddenly throw an Exception(java.lang.SecurityException) that will lead to the application crashing. Hence we need to implement this new android permissions model in our application.

Dangerous and Normal android permissions

Android defines some permissions as dangerous and some as normal. The common thing in both the types is that they need to be defined in the Manifest file. From Android 6.0 only dangerous permissions are checked at runtime, normal permissions are not. An example of a normal permission is android.permission.INTERNET. Dangerous permissions are grouped into categories that make it easier for the user to understand what they are allowing the application to do. If the user accepts one permission in a group/category they accept the entire group. An example of dangerous permission is android.permission.FINE_LOCATION and android.permission.COARSE_LOCATION. Enabling anyone of the location permissions enables all.

Requesting Android Runtime Permissions

The method requestPermissions(String[] permissions, int requestCode); is a public method that is used to request dangerous permissions. We can ask for multiple dangerous permissions by passing a string array of permissions. Note: Android Permissions belonging to two different groups would prompt the user with an individual dialog for each of them. If they belong to the same group, then only one dialog prompt would be displayed. The results of the requests will be passed into the method onRequestPermissionResult. Example : Let’s say we want to access the camera and location in our app. Both are dangerous permissions. We’ll display a prompt requesting access to these permissions when the application is launched. Let’s add the permissions into a string array and call the requestPermissions as shown below:

String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};

int permsRequestCode = 200; 
requestPermissions(perms, permsRequestCode);

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){

    switch(permsRequestCode){

        case 200:

            boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
            boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;

            break;

    }

}

Now we don’t want the user to keep accepting permissions that he’s already accepted. Even if the permission has been previously granted it is necessary to check again to be sure that the user did not later revoke that permission. For this the following method needs to be called on every permission.

checkSelfPermission(String perm);

It returns an integer value of PERMISSION_GRANTED or PERMISSION_DENIED. Note: If a user declines a permission that is critical in the app, then shouldShowRequestPermissionRationale(String permission); is used to describe the user the need for the permission. Let’s develop an application which checks if the permission is already present. If not, then it’s requested at runtime.

Android Runtime Permissions Project Structure

android runtime permissions project

Android Runtime PermissionsCode

The content_main.xml contains the two buttons to check and request permissions.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.journaldev.runtimepermissions.MainActivity"
    tools:showIn="@layout/activity_main">
    <Button
        android:id="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Check Permission"/>
    <Button
        android:id="@+id/request_permission"
        android:layout_below="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request Permission"/>
</RelativeLayout>

The MainActivity.java is defined as below.

package com.journaldev.runtimepermissions;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int PERMISSION_REQUEST_CODE = 200;
    private View view;


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

        Button check_permission = (Button) findViewById(R.id.check_permission);
        Button request_permission = (Button) findViewById(R.id.request_permission);
        check_permission.setOnClickListener(this);
        request_permission.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {

        view = v;

        int id = v.getId();
        switch (id) {
            case R.id.check_permission:
                if (checkPermission()) {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                } else {

                    Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
                }
                break;
            case R.id.request_permission:
                if (!checkPermission()) {

                    requestPermission();

                } else {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                }
                break;
        }

    }

    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);

        return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermission() {

        ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0) {

                    boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;

                    if (locationAccepted && cameraAccepted)
                        Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
                    else {

                        Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                                showMessageOKCancel("You need to allow access to both the permissions",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                    requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
                                                            PERMISSION_REQUEST_CODE);
                                                }
                                            }
                                        });
                                return;
                            }
                        }

                    }
                }


                break;
        }
    }


    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

}

Note: Add the permissions that are to be checked at runtime in the Manifest file above the application tag as;

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

In the above code the two permissions that are checked and requested are CAMERA and LOCATION. Importing the static permission full class name allows us to write just the PERMISSION object instead of the fully qualified path. checkPermission() calls the checkSelfPermission on each of the permissions. requestPermission() calls ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);. onRequestPermissionsResult checks if the permissions are granted or not. In our code if both the permissions are not granted an alert dialog is popped showing the mandatory need to request the permissions. To do that shouldShowRequestPermissionRationale(String permission) is invoked which invokes an alert dialog showing the need for the permissions. You can revoke the permissions manually from Settings->Apps->Permissions. Note: The runtime permission specific methods are available only since API 23. Hence the following condition is checked at each of the methods :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)

The output of the android runtime permissions example application in action is given below. android runtime permissions example This brings an end to this tutorial. You can download the final Android Runtime Permissions project from the link below.

Download Android Runtime Permission Example Project

Reference: https://developer.android.com/training/permissions/requesting.html

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Anupam Chugh

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
March 2, 2021

Do you have completed list of permission that we should check at run time. I need it

- Bagus

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    January 28, 2021

    Thank you, for the very concise and pertinent code sample!

    - Zielniq

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      October 15, 2019

      Hello brother how are you? can you tell what is signature permission in android with some implemented example? Thank you

      - Awais Khan

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        August 5, 2019

        Not working in my project ,camera permission properly work, but not working loction access permission

        - Dheeraj Sharma

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          February 18, 2019

          Thank you very much man. I was looking for a kotlin version but this Java version helped me work around things in Kotlin and it worked perfect.

          - Simba Mupfu

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            January 1, 2019

            thank you…its working

            - Athul Thomas

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              December 28, 2018

              good example it help me a lot of help in my work

              - savan

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                September 28, 2018

                I found really useful this repo https://github.com/joseph280/RuntimePermissionsJoseph

                - S3rialKill3r

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  October 25, 2017

                  It is best!! But what about for API level < 23?

                  - Isaac

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    September 22, 2017

                    HI Thanks a lot for this great explanation regarding android M permissions model. i have a question though, when a the user ‘Deny’ the permissions then application crashes with java.lang.SecurityException, when user try to use feature related to permissions, then how can we avoid our app from crash?

                    - saqib

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.