How to Handle Runtime Permissions In Android

Handle-Runtime-Permissions-In-Android

27th February, 2020

In this example, You will learn how to handle the runtime permissions in Android.

Step 1: Create New Project

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

Step 2: Add Permissions

Add required permissions to the AndroidManifest.xml

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

Step 3: Handle Runtime Permissions

Create a util class and add following methods.

package com.codestringz.mytestapp;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class Util
{
    public static void requestPermissions(Context context, @NonNull String[] appPermissions, int reqCode)
    {
        List<String> listPermissionsNeeded = new ArrayList<>();

        for (String permission : appPermissions)
        {
            if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
            {
                listPermissionsNeeded.add(permission);
            }
        }
        if (!listPermissionsNeeded.isEmpty())
        {
            ActivityCompat.requestPermissions((Activity) context, listPermissionsNeeded.toArray(new String[0]), reqCode);
        }
    }

    public static boolean isAllPermissionsGranted(Context context, @NonNull String[] appPermissions)
    {
        for (String permission : appPermissions)
        {
            if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
            {
                return false;
            }
        }
        return true;
    }
}

Add some strings to the strings.xml

<resources>
    <string name="app_name">My Test App</string>

    <string name="msg_yes_permissions_granted">Yes, Permissions Granted!</string>
        <string name="msg_everything_is_okay">Everything is okay!</string>
        <string name="msg_req_permission_try_again">Permission required for this app. Do you want to try again?</string>
        <string name="try_again">Try again?</string>
        <string name="msg_open_settings">Do you want to open app settings to enable required permissions?</string>
        <string name="tag_package">package</string>
        <string name="msg_permissions_granted_do_anything">Perms granted, do anything!</string>
        <string name="OK">OK</string>
        <string name="cancel">Cancel</string>
    <string name="request_permissions">Request Permissions</string>
    <string name="www_codestringz_com">www.CodestringZ.com</string>
</resources>

Open the activity and request the runtime permissions.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/hintTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/www_codestringz_com" />

    <Button
        android:id="@+id/testButton"
        android:text="@string/request_permissions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"/>

</LinearLayout>
package com.codestringz.mytestapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity
{

    private static final int CODE_MULTIPLE_PERMISSIONS = 558;
    private static final int CODE_APP_SETTING = CODE_MULTIPLE_PERMISSIONS + 1;

    //List of Permissions, You can add single permission as well
    private final String[] APP_PERMISSIONS = new String[]
            {
                    Manifest.permission.CAMERA,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
            };

    private TextView mHintTextView;

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

        setUIRef();

        reqPermissions();
    }

    private void setUIRef()
    {
        mHintTextView = findViewById(R.id.hintTextView);

        Button testButton = findViewById(R.id.testButton);
        testButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                reqPermissions();
            }
        });
    }

    private void reqPermissions()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            if (Util.isAllPermissionsGranted(this, APP_PERMISSIONS))
            {
                //Permissions Granted
                mHintTextView.setText(getResources().getString(R.string.msg_yes_permissions_granted));
            } else
            {
                //Permissions Not Granted
                Util.requestPermissions(MainActivity.this, APP_PERMISSIONS, CODE_MULTIPLE_PERMISSIONS);
            }
        } else
        {
            mHintTextView.setText(getResources().getString(R.string.msg_everything_is_okay));
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
    {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == CODE_MULTIPLE_PERMISSIONS)
        {
            boolean allGranted = true;
            int nonGrantedPermissionIndex = -2;

            if (grantResults.length > 0)
            {
                for (int i = 0; i < grantResults.length; i++)
                {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED)
                    {
                        allGranted = false;
                        nonGrantedPermissionIndex = i;
                        break;
                    }
                }
            }
            if (!allGranted)
            {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[nonGrantedPermissionIndex]))
                {
                    //Show the dialog to grant the necessary permissions
                    showDialogOK(getResources().getString(R.string.msg_req_permission_try_again), new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int which)
                        {
                            switch (which)
                            {
                                case DialogInterface.BUTTON_NEGATIVE:
                                    mHintTextView.setText(getResources().getString(R.string.try_again));
                                    break;
                                case DialogInterface.BUTTON_POSITIVE:
                                    //Request again
                                    Util.requestPermissions(getApplicationContext(), APP_PERMISSIONS, CODE_MULTIPLE_PERMISSIONS);
                                    break;
                            }
                        }
                    });
                } else
                {
                    //Show the dialog to open app settings
                    showDialogOK(getResources().getString(R.string.msg_open_settings), new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int which)
                        {
                            switch (which)
                            {
                                case DialogInterface.BUTTON_NEGATIVE:
                                    mHintTextView.setText(getResources().getString(R.string.try_again));
                                    break;
                                case DialogInterface.BUTTON_POSITIVE:
                                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts(getResources().getString(R.string.tag_package), getPackageName(), null);
                                    intent.setData(uri);
                                    startActivityForResult(intent, CODE_APP_SETTING);
                                    break;
                            }
                        }
                    });
                }
            } else
            {
                //All Granted, do anything!
                mHintTextView.setText(getResources().getString(R.string.msg_permissions_granted_do_anything));
            }
        }
    }

    private void showDialogOK(String message, DialogInterface.OnClickListener okListener)
    {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton(getResources().getString(R.string.OK), okListener)
                .setNegativeButton(getResources().getString(R.string.cancel), okListener)
                .create()
                .show();
    }
}

Happy coding!

Leave a Reply