Android 6.0 multiple permissions

202,960

Solution 1

Just include all 4 permissions in the ActivityCompat.requestPermissions(...) call and Android will automatically page them together like you mentioned.

I have a helper method to check multiple permissions and see if any of them are not granted.

public static boolean hasPermissions(Context context, String... permissions) {
    if (context != null && permissions != null) {
        for (String permission : permissions) {
            if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
    }
    return true;
}

Or in Kotlin:

fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
    ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}

Then just send it all of the permissions. Android will ask only for the ones it needs.

// The request code used in ActivityCompat.requestPermissions()
// and returned in the Activity's onRequestPermissionsResult()
int PERMISSION_ALL = 1; 
String[] PERMISSIONS = {
  android.Manifest.permission.READ_CONTACTS, 
  android.Manifest.permission.WRITE_CONTACTS, 
  android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 
  android.Manifest.permission.READ_SMS, 
  android.Manifest.permission.CAMERA
};

if (!hasPermissions(this, PERMISSIONS)) {
    ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}

Solution 2

Here is detailed example with multiple permission requests:-

The app needs 2 permissions at startup . SEND_SMS and ACCESS_FINE_LOCATION (both are mentioned in manifest.xml).

I am using Support Library v4 which is prepared to handle Android pre-Marshmallow and so no need to check build versions.

As soon as the app starts up, it asks for multiple permissions together. If both permissions are granted the normal flow goes.

enter image description here

enter image description here

public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(checkAndRequestPermissions()) {
        // carry on the normal flow, as the case of  permissions  granted.
    }
}

private  boolean checkAndRequestPermissions() {
    int permissionSendMessage = ContextCompat.checkSelfPermission(this,
            Manifest.permission.SEND_SMS);
    int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();
    if (locationPermission != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
    }
    if (!listPermissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    return true;
}

ContextCompat.checkSelfPermission(), ActivityCompat.requestPermissions(), ActivityCompat.shouldShowRequestPermissionRationale() are part of support library.

In case one or more permissions are not granted, ActivityCompat.requestPermissions() will request permissions and the control goes to onRequestPermissionsResult() callback method.

You should check the value of shouldShowRequestPermissionRationale() flag in onRequestPermissionsResult() callback method.

There are only two cases:--

Case 1:-Any time user clicks Deny permissions (including the very first time), it will return true. So when the user denies, we can show more explanation and keep asking again

Case 2:-Only if user select “never asks again” it will return false. In this case, we can continue with limited functionality and guide user to activate the permissions from settings for more functionalities, or we can finish the setup, if the permissions are trivial for the app.

CASE -1

enter image description here

CASE-2

enter image description here

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        Log.d(TAG, "Permission callback called-------");
        switch (requestCode) {
            case REQUEST_ID_MULTIPLE_PERMISSIONS: {

                Map<String, Integer> perms = new HashMap<>();
                // Initialize the map with both permissions
                perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
                perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
                // Fill with actual results from user
                if (grantResults.length > 0) {
                    for (int i = 0; i < permissions.length; i++)
                        perms.put(permissions[i], grantResults[i]);
                    // Check for both permissions
                    if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        Log.d(TAG, "sms & location services permission granted");
                        // process the normal flow
                        //else any one or both the permissions are not granted
                    } else {
                            Log.d(TAG, "Some permissions are not granted ask again ");
                            //permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
//                        // shouldShowRequestPermissionRationale will return true
                            //show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
                            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
                                showDialogOK("SMS and Location Services Permission required for this app",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                switch (which) {
                                                    case DialogInterface.BUTTON_POSITIVE:
                                                        checkAndRequestPermissions();
                                                        break;
                                                    case DialogInterface.BUTTON_NEGATIVE:
                                                        // proceed with logic by disabling the related features or quit the app.
                                                        break;
                                                }
                                            }
                                        });
                            }
                            //permission is denied (and never ask again is  checked)
                            //shouldShowRequestPermissionRationale will return false
                            else {
                                Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
                                        .show();
    //                            //proceed with logic by disabling the related features or quit the app.
                            }
                    }
                }
            }
        }

    }

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

Solution 3

Small code :

 public static final int MULTIPLE_PERMISSIONS = 10; // code you want.

 String[] permissions= new String[]{
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION};


if (checkPermissions())
         //  permissions  granted.    
}

private  boolean checkPermissions() {
        int result;
        List<String> listPermissionsNeeded = new ArrayList<>();
        for (String p:permissions) {
            result = ContextCompat.checkSelfPermission(getActivity(),p);
            if (result != PackageManager.PERMISSION_GRANTED) {
                listPermissionsNeeded.add(p);
            }
        }
        if (!listPermissionsNeeded.isEmpty()) {
            ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
            return false;
        }
        return true;
    }


   @Override
    public void onRequestPermissionsResult(int requestCode, String permissionsList[], int[] grantResults) {
        switch (requestCode) {
            case MULTIPLE_PERMISSIONS:{
                if (grantResults.length > 0) {
                String permissionsDenied = "";
                for (String per : permissionsList) {
                    if(grantResults[0] == PackageManager.PERMISSION_DENIED){
                        permissionsDenied += "\n" + per;

                    } 

                }
                // Show permissionsDenied 
                updateViews();
            }
                return;
            }
        }
     }

List of Android permissions normal permissions and dangerous permissions in API 23

Solution 4

In a Fragment

public class Homefragment extends Fragment {
    View hfrag;
   Context context;
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

//first we must check the permissions are already granted

        hfrag = inflater.inflate(R.layout.home, container, false);
        context = getActivity();
checkAndRequestPermissions();

}




}


private boolean checkAndRequestPermissions() {
        int permissionSendMessage = ContextCompat.checkSelfPermission(context,
                Manifest.permission.READ_SMS);
        int contactpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS);

        int writepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);

        int callpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE);

        int receivepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS);
        int locationpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);

        List<String> listPermissionsNeeded = new ArrayList<>();

        if (locationpermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }

        if (contactpermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.GET_ACCOUNTS);
        }
        if (writepermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.READ_SMS);
        }
        if (receivepermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.RECEIVE_SMS);
        }

        if (callpermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.CALL_PHONE);
        }
        if (!listPermissionsNeeded.isEmpty()) {
            requestPermissions(listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
            return false;
        }
        return true;
    }



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


    if (requestCode == REQUEST_ID_MULTIPLE_PERMISSIONS) {


        if (grantResults.length > 0) {
            for (int i = 0; i < permissions.length; i++) {


                if (permissions[i].equals(Manifest.permission.GET_ACCOUNTS)) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("msg", "accounts granted");

                    }
                } else if (permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("msg", "storage granted");

                    }
                } else if (permissions[i].equals(Manifest.permission.CALL_PHONE)) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("msg", "call granted");

                    }
                } else if (permissions[i].equals(Manifest.permission.RECEIVE_SMS)) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("msg", "sms granted");

                    }
                } else if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("msg", "location granted");

                    }
                }


            }

        }


    }
}

}

Solution 5

It's easy, do this way

private static final int REQUEST_READ_PHONE_STATE = 110 , REQUEST_ACCESS_FINE_LOCATION = 111, REQUEST_WRITE_STORAGE = 112;

In your onCreate

 //request permission
    boolean hasPermissionPhoneState = (ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermissionPhoneState) {
        ActivityCompat.requestPermissions(LoginActivity.this,
                new String[]{Manifest.permission.READ_PHONE_STATE},
                REQUEST_READ_PHONE_STATE);
    }

    boolean hasPermissionLocation = (ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermissionLocation) {
        ActivityCompat.requestPermissions(LoginActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_ACCESS_FINE_LOCATION);
    }

    boolean hasPermissionWrite = (ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermissionWrite) {
        ActivityCompat.requestPermissions(LoginActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_STORAGE);
    }

Then check result

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {
        case REQUEST_READ_PHONE_STATE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
                //reload my activity with permission granted or use the features what required the permission
                finish();
                startActivity(getIntent());
            } else
            {
                Toast.makeText(LoginActivity.this, "The app was not allowed to get your phone state. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }
        case REQUEST_ACCESS_FINE_LOCATION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
                //reload my activity with permission granted or use the features what required the permission
                finish();
                startActivity(getIntent());
            } else
            {
                Toast.makeText(LoginActivity.this, "The app was not allowed to get your location. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }

        case REQUEST_WRITE_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
                //reload my activity with permission granted or use the features what required the permission
                finish();
                startActivity(getIntent());
            } else
            {
                Toast.makeText(LoginActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }
    }

}
Share:
202,960

Related videos on Youtube

Frank
Author by

Frank

Updated on February 23, 2022

Comments

  • Frank
    Frank about 2 years

    I know that Android 6.0 has new permissions and I know I can call them with something like this

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
        PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
            new String[] { 
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, PERMISSION_WRITE_STORAGE);
    }
    

    Today I saw a Google app which needs 3 permissions: contacts, sms and camera. It's making a page 1-3 and calls them all together at the same time to activate.

    Can anybody tell me how I can call 4 permissions to activate at the same time like sms, camera, contacts and storage?

    Example (forgot the name of the google app :( )
    The app needs sms,contacts and camera

    the app asked me (and made a dialog page1-3) activate sms, activate contacts and then camera. So this google app was calling all 3 required permissions together and my question is how can i achive the same ?

    • kandroidj
      kandroidj over 8 years
      can you be more specific or share what you have seen and want to implement?
    • Frank
      Frank over 8 years
      Calling all 4 permissions at the same time in android 6.0 because "this" app needs 4 permissions. and this google app made it very smart calling them all together and as i mentiond makes page 1-3 to activate all 3 on the fly ..so how can i make the same ? calling 4 permissions together at the same time to activate them
    • natario
      natario over 8 years
      Just add all the permissions you wish inside the String[] array.
  • Frank
    Frank over 8 years
    Hi Owls thanx but this is not my question. I want call 4 different permission at the same time from 4 permission groups. Call them all together so the user can activate them all in one step ..one google app makes the same possible
  • Frank
    Frank over 8 years
    ...no sorry Owls ..got it know ..i think you are right ! Will try this out thanx
  • Frank
    Frank over 8 years
    Thanx James i think this is exactly what i need ... !!
  • Frank
    Frank over 8 years
    Hi James yes your solution works perfect !!! Many thanx again ! just changed DeviceUtils.Hasmarshmallow() to (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) . I think this is better
  • kbonnelly
    kbonnelly almost 8 years
    It solved my problem too, thank you. @Frank if this solved your problem, don't forget to accept this answer so everybody can quickly see it.
  • Harsha
    Harsha almost 8 years
    but its showing all permission dialogs multiple times
  • Yar
    Yar almost 8 years
    You say "You should check the value of shouldShowRequestPermissionRationale() flag in onRequestPermissionsResult() callback method. " but developer.android.com/training/permissions/requesting.html advises to call shouldShowRequestPermissionRationale() before requesting permissions. I am confused. Your code looks more reasonable but you never know with Google...
  • hasnain_ahmad
    hasnain_ahmad over 7 years
    What will be the value of PERMISSION_ALL in the above code?
  • James McCracken
    James McCracken over 7 years
    It's an integer constant used to identify the request in the callback. See developer.android.com/reference/android/support/v4/app/…
  • Maveňツ
    Maveňツ over 7 years
    @JamesMcCracken thanks for the code .. but it always keep asking me for permission, doesn't matters whether I already granted or not.
  • MohanRaj S
    MohanRaj S over 7 years
    Thanks Nick, how to do sequential permission popup? please guide me to fix this issue
  • chengsam
    chengsam over 7 years
    @maveň I am facing the same problem.. If I do not grant 1 of them, it will ask all permissions again including others that I already granted.
  • Yogesh Patel
    Yogesh Patel over 7 years
    This worked perfectly for me.. just a question, can we disable touch events oustide alert dialogs when these alert dialogs appear. Because in my case I want the users to allow permissions and then only access the app.
  • Tharindu Bandara
    Tharindu Bandara over 7 years
    @YogeshPatel Anytime dude.. when these alert dialogs appear, the outside touch is automatically desabled except the Status bar. then you only have two options - DENY or ALLOW. Don't forget to add all permissions to your Main activity. You can hide the status bar, check this Hiding the Status Bar
  • Keshav
    Keshav over 7 years
    I like the way this has been written. But can you show how you are handling multiple results in the onRequestPermissionsResult() method.
  • Ahmed Samir
    Ahmed Samir about 7 years
    dear all why i keep got error in this cannot resolve symbol : REQUEST_ID_MULTIPLE_PERMISSIONS
  • CrazyMind
    CrazyMind about 7 years
    @JamesMcCracken hi using this code first time code run perfectly, but after restart app it fail while checking permission Code like this
  • Alex Berdnikov
    Alex Berdnikov almost 7 years
    Great solution! Although, I'm curious if API version check is really needed? I think if it's pre-Marshmallow OS permissions are granted on installation and then there's simply no reason to check the version.
  • Antonino
    Antonino over 6 years
    this answer is better than Google documentation, well done!
  • Oliver Burdekin
    Oliver Burdekin about 6 years
    This is a tidy solution. I've taken out the version check (@AlexBerdnikov is correct). However, I've noticed that when asking for multiple permissions the "don't ask again" check box is replaced with a counter (1 of 3... 2 of 3 etc). Just an observation.
  • AppEmmanuel
    AppEmmanuel almost 6 years
    Nice one, @JamesMcCracken. Thanks. I only had to add "android." to "Manifest. ..."
  • LizG
    LizG over 5 years
    This was very helpful to me
  • Debasish Ghosh
    Debasish Ghosh over 5 years
    How to handle when user blocks one request ?
  • ozzyzig
    ozzyzig about 5 years
    Nice one! @JamesMcCracken
  • Abilash
    Abilash about 5 years
    @AhmedSamir you need to define REQUEST_ID_MULTIPLE_PERMISSIONS eg. int REQUEST_ID_MULTIPLE_PERMISSIONS = 100;
  • Elliptica
    Elliptica about 5 years
    Hi, is there a way to have multiple request codes? Like if we wanted different behavior based on grant/refuse for the different permissions we request?
  • Newton_Jose
    Newton_Jose almost 5 years
    Very nice! Below I put a answer with Kotlin equivalent code.
  • Oke Uwechue
    Oke Uwechue over 4 years
    Nice and neat solution. Helper class helps to unclutter main code.
  • zulu_papa
    zulu_papa over 4 years
    Thank you, i have applied the code to my app. Works fine, thanks once more!!!
  • RonTLV
    RonTLV over 4 years
    Please give a java example
  • shinsky Paul
    shinsky Paul over 3 years
    @Andrew Vovk, this is great. How do you handle alternative user reponses e.g Allow for Location and Deny for Storage? I am getting this error on testing an Allow and Deny 'FATAL EXCEPTION: main Failure delivering result ResultInfo{who=@android:requestPermissions:, request=100, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }}'
  • superjos
    superjos over 3 years
    I know this is quite late, but just for anyone coming here: is that ok to always check grantResults[0] at index 0, even for futher items in permissionsList? Shouldn't permissionsList and grantResults be considered as side-by-side arrays?
  • Mike Debela
    Mike Debela almost 3 years
    Type mismatch on (!hasPermissions(this, PERMISSIONS))
  • shohag khan
    shohag khan over 2 years
    This is very easy, but if CAMERA allowed I want to do something and READ_PHONE_STATE is not allowed I want to do something else. How can I handle multiple different situation?
  • DikShU
    DikShU over 2 years
    what is update views?? here
  • kirkadev
    kirkadev over 2 years
    Thank you for your answer. Note for using with Kotlin: You should call hasPermissions(...) method with " * " symbol like this: (!hasPermissions(this, *PERMISSIONS))