Android 6.0 multiple permissions
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.
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
CASE-2
@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();
}
}
}
}
Related videos on Youtube
Frank
Updated on February 23, 2022Comments
-
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 camerathe 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 over 8 yearscan you be more specific or share what you have seen and want to implement?
-
Frank over 8 yearsCalling 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 over 8 yearsJust add all the permissions you wish inside the String[] array.
-
-
Frank over 8 yearsHi 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 over 8 years...no sorry Owls ..got it know ..i think you are right ! Will try this out thanx
-
Frank over 8 yearsThanx James i think this is exactly what i need ... !!
-
Frank over 8 yearsHi 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 almost 8 yearsIt 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 almost 8 yearsbut its showing all permission dialogs multiple times
-
Yar almost 8 yearsYou 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 over 7 yearsWhat will be the value of
PERMISSION_ALL
in the above code? -
James McCracken over 7 yearsIt's an integer constant used to identify the request in the callback. See developer.android.com/reference/android/support/v4/app/…
-
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 over 7 yearsThanks Nick, how to do sequential permission popup? please guide me to fix this issue
-
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 over 7 yearsThis 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 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 over 7 yearsI like the way this has been written. But can you show how you are handling multiple results in the onRequestPermissionsResult() method.
-
Ahmed Samir about 7 yearsdear all why i keep got error in this cannot resolve symbol : REQUEST_ID_MULTIPLE_PERMISSIONS
-
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 almost 7 yearsGreat 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 over 6 yearsthis answer is better than Google documentation, well done!
-
Oliver Burdekin about 6 yearsThis 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 almost 6 yearsNice one, @JamesMcCracken. Thanks. I only had to add "android." to "Manifest. ..."
-
LizG over 5 yearsThis was very helpful to me
-
Debasish Ghosh over 5 yearsHow to handle when user blocks one request ?
-
ozzyzig about 5 yearsNice one! @JamesMcCracken
-
Abilash about 5 years@AhmedSamir you need to define REQUEST_ID_MULTIPLE_PERMISSIONS eg. int REQUEST_ID_MULTIPLE_PERMISSIONS = 100;
-
Elliptica about 5 yearsHi, 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 almost 5 yearsVery nice! Below I put a answer with Kotlin equivalent code.
-
Oke Uwechue over 4 yearsNice and neat solution. Helper class helps to unclutter main code.
-
zulu_papa over 4 yearsThank you, i have applied the code to my app. Works fine, thanks once more!!!
-
RonTLV over 4 yearsPlease give a java example
-
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 over 3 yearsI 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 inpermissionsList
? Shouldn'tpermissionsList
andgrantResults
be considered as side-by-side arrays? -
Mike Debela almost 3 yearsType mismatch on
(!hasPermissions(this, PERMISSIONS))
-
shohag khan over 2 yearsThis 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 over 2 yearswhat is update views?? here
-
kirkadev over 2 yearsThank you for your answer. Note for using with Kotlin: You should call hasPermissions(...) method with " * " symbol like this: (!hasPermissions(this, *PERMISSIONS))