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 ?
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);
}
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();
}
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
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");
}
}
}
}
}
}
}
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();
}
}
}
}
My approach is based on Nicks' answer and hopefully is a bit more usable for multiple (as many as needed, not only two) permissions.
It suggests adding single-responsibility PermissionsHelper class:
import android.app.Activity;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PermissionsHelper {
private static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 100; // any code you want.
public void checkAndRequestPermissions(Activity activity, String... permissions) {
List<String> listPermissionsNeeded = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(permission);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(activity, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
}
}
public void onRequestPermissionsResult(Activity activity, int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
for (String permission : permissions) {
perms.put(permission, PackageManager.PERMISSION_GRANTED);
}
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
boolean allPermissionsGranted = true;
for (String permission1 : permissions) {
allPermissionsGranted = allPermissionsGranted && (perms.get(permission1) == PackageManager.PERMISSION_GRANTED);
}
if (allPermissionsGranted) {
Log.d(PermissionsHelper.class.getSimpleName(), "onRequestPermissionsResult: all permissions granted");
} else {
for (String permission2 : perms.keySet())
if (perms.get(permission2) == PackageManager.PERMISSION_GRANTED)
perms.remove(permission2);
StringBuilder message = new StringBuilder("The app has not been granted permissions:\n\n");
for (String permission : perms.keySet()) {
message.append(permission);
message.append("\n");
}
message.append("\nHence, it cannot function properly." +
"\nPlease consider granting it this permission in phone Settings.");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.permission_required)
.setMessage(message)
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel());
AlertDialog alert = builder.create();
alert.show();
}
}
}
}
}
}
If one or several required permissions have not been granted by user, the detailed AlertDialog message will be shown to him.
Example of usage in Activity:
private PermissionsHelper permissionsHelper;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkPermissions();
//any other code
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsHelper.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
}
private void checkPermissions() {
permissionsHelper = new PermissionsHelper();
permissionsHelper.checkAndRequestPermissions(this,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
}
Hope that this will be useful for someone.
My handler class for request multiple permissions. You can check the full using here
public class RequestPermissionHandler {
private Activity mActivity;
private RequestPermissionListener mRequestPermissionListener;
private int mRequestCode;
public void requestPermission(Activity activity, #NonNull String[] permissions, int requestCode,
RequestPermissionListener listener) {
mActivity = activity;
mRequestCode = requestCode;
mRequestPermissionListener = listener;
if (!needRequestRuntimePermissions()) {
mRequestPermissionListener.onSuccess();
return;
}
requestUnGrantedPermissions(permissions, requestCode);
}
private boolean needRequestRuntimePermissions() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private void requestUnGrantedPermissions(String[] permissions, int requestCode) {
String[] unGrantedPermissions = findUnGrantedPermissions(permissions);
if (unGrantedPermissions.length == 0) {
mRequestPermissionListener.onSuccess();
return;
}
ActivityCompat.requestPermissions(mActivity, unGrantedPermissions, requestCode);
}
private boolean isPermissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(mActivity, permission)
== PackageManager.PERMISSION_GRANTED;
}
private String[] findUnGrantedPermissions(String[] permissions) {
List<String> unGrantedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (!isPermissionGranted(permission)) {
unGrantedPermissionList.add(permission);
}
}
return unGrantedPermissionList.toArray(new String[0]);
}
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mRequestPermissionListener.onFailed();
return;
}
}
mRequestPermissionListener.onSuccess();
} else {
mRequestPermissionListener.onFailed();
}
}
}
public interface RequestPermissionListener {
void onSuccess();
void onFailed();
}
}
Refer this link for full understand of multiple permission, also full source code download, click Here
private boolean checkAndRequestPermissions() {
int permissionReadPhoneState = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
int permissionProcessOutGogingCalls = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS);
int permissionProcessReadContacts = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
int permissionProcessReadCallLog = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG);
int permissionWriteStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionReadStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionReadPhoneState != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
}
if (permissionProcessOutGogingCalls != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
}
if (permissionProcessReadContacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CONTACTS);
}
if (permissionProcessReadCallLog != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CALL_LOG);
}
if (permissionWriteStorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionReadStorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length == 0 || grantResults == null) {
/*If result is null*/
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
/*If We accept permission*/
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
/*If We Decline permission*/
}
}
The following methodology is about
asking permissions dynamically ;
showing a AlertDialog if the user denies any permission
looping until the user accepts permission(s)
Create a "static" class for permissions methods
public class PermissionsUtil {
public static final int PERMISSION_ALL = 1;
public static boolean doesAppNeedPermissions(){
return android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
}
public static String[] getPermissions(Context context)
throws PackageManager.NameNotFoundException {
PackageInfo info = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_PERMISSIONS);
return info.requestedPermissions;
}
public static void askPermissions(Activity activity){
if(doesAppNeedPermissions()) {
try {
String[] permissions = getPermissions(activity);
if(!checkPermissions(activity, permissions)){
ActivityCompat.requestPermissions(activity, permissions,
PERMISSION_ALL);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
public static boolean checkPermissions(Context context, String... permissions){
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null &&
permissions != null) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
}
In MainActivity.java
private void checkPermissions(){
PermissionsUtil.askPermissions(this);
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PermissionsUtil.PERMISSION_ALL: {
if (grantResults.length > 0) {
List<Integer> indexesOfPermissionsNeededToShow = new ArrayList<>();
for(int i = 0; i < permissions.length; ++i) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
indexesOfPermissionsNeededToShow.add(i);
}
}
int size = indexesOfPermissionsNeededToShow.size();
if(size != 0) {
int i = 0;
boolean isPermissionGranted = true;
while(i < size && isPermissionGranted) {
isPermissionGranted = grantResults[indexesOfPermissionsNeededToShow.get(i)]
== PackageManager.PERMISSION_GRANTED;
i++;
}
if(!isPermissionGranted) {
showDialogNotCancelable("Permissions mandatory",
"All the permissions are required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
checkPermissions();
}
});
}
}
}
}
}
}
private void showDialogNotCancelable(String title, String message,
DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setCancelable(false)
.create()
.show();
}
🔥 NEW EASY AND CLEAN WAY OF ASKING MULTIPLE PERMISSIONS IN 2022 🔥
At the top of your activity class, write
private val multiplePermissionContract = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissionsStatusMap ->
// permissionStatusMap is of type <String, Boolean>
// if all permissions accepted
if (!permissionsStatusMap.containsValue(false)) {
// All persmissions are accepted, do here whatever you want
} else {
Toast.makeText(this, "all permissions not accepted", Toast.LENGTH_SHORT).show()
}
}
And, launch the permission asking dialogs whenever you want like below(for now, I am thinking that you need to ask the permissions when you click on xyzButton)
xyzButton.setOnClickListener {
multiplePermissionContract.launch(
arrayOf(
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
)
)
}
NOTE -
registerForActivityResult() method will always be called whenever we click on xyzButton. If all any of the all permissions is not accepted earlier, it will ask that particular permission again; else it will directly execute the if condition block.
There is nothing wrong with answers asking for multiple permissions but multiple permission result code is not implemented very elegantly and may cause checking wrong permission result.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) is terrible logic for checking multiple permissions result, i don't know why Google implemented such a terrible code.
It's a mess especially when you check multiple permissions. Let say you ask for CAMERA, ACCESS_FINE_LOCATION and ACCESS_NETWORK_STATE.
You need to check for ACCESS_FINE_LOCATION but user only granted CAMERA at first run and you check for grantResults[1] but in second run ACCESS_FINE_LOCATION becomes the permission with index 0. I got so many problems with user not granting all permissions at once and have to write so pointless permission result logic.
You should either use
int size = permissions.length;
boolean locationPermissionGranted = false;
for (int i = 0; i < size; i++) {
if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)
&& grantResults[i] == PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true;
}
}
Or simpler one
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
// Do something ...
}
in onPermissionRequestResult method.
Checking every situation
if denied - showing Alert dialog to user why we need permission
public static final int MULTIPLE_PERMISSIONS = 1;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 2;
public static final int STORAGE_PERMISSION_REQUEST_CODE = 3;
private void askPermissions() {
int permissionCheckStorage = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionCheckCamera = ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA);
// we already asked for permisson & Permission granted, call camera intent
if (permissionCheckStorage == PackageManager.PERMISSION_GRANTED && permissionCheckCamera == PackageManager.PERMISSION_GRANTED) {
launchCamera();
} //asking permission for the first time
else if (permissionCheckStorage != PackageManager.PERMISSION_GRANTED && permissionCheckCamera != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
MULTIPLE_PERMISSIONS);
} else {
// Permission denied, so request permission
// if camera request is denied
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("You need to give permission to take pictures in order to work this feature.");
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.setPositiveButton("GIVE PERMISSION", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
// Show permission request popup
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
CAMERA_PERMISSION_REQUEST_CODE);
}
});
builder.show();
} // if storage request is denied
else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("You need to give permission to access storage in order to work this feature.");
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.setPositiveButton("GIVE PERMISSION", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
// Show permission request popup
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
STORAGE_PERMISSION_REQUEST_CODE);
}
});
builder.show();
}
}
}
Checking Permission Results
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case CAMERA_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.CAMERA)) {
// check whether camera permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
case STORAGE_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// check whether storage permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
case MULTIPLE_PERMISSIONS:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.CAMERA) && permissions[1].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// check whether All permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
default:
break;
}
}
you can just copy and paste this code, it works fine. change context(this) & permissions according to you.
Short and sweet :). what I believe in.
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}; // List of permissions required
public void askPermission()
{
for (String permission : PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(PERMISSIONS, PERMISSION_ALL);
return;
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case 1:{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
//Do your work.
} else {
Toast.makeText(this, "Until you grant the permission, we cannot proceed further", Toast.LENGTH_SHORT).show();
}
return;
}
}
After seeing all the long and complex answers. I want post this answer.
RxPermission is widely used library now for asking permission in one line code.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.subscribe(granted -> {
if (granted) {
// All requested permissions are granted
} else {
// At least one permission is denied
}
});
add in your build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}
Isn't this easy?
I have successfully implemented simple code for Multiple permission at Once.
Follow the below steps
1:Make Utility.java class like below
public class Utility {
public static final int MY_PERMISSIONS_REQUEST = 123;
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static boolean checkPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission)) {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE,Manifest.permission.GET_ACCOUNTS}, MY_PERMISSIONS_REQUEST);
} else {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE,Manifest.permission.GET_ACCOUNTS}, MY_PERMISSIONS_REQUEST);
}
return false;
}
}
}
return true;
}
}
2: Now call
boolean permissionCheck = Utility.checkPermissions(this, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE, Manifest.permission.GET_ACCOUNTS);
in your Activity onCreate() or according to your logic.
3:Now check permission before performing operation for particular task
if (permissionCheck) {
performTaskOperation();//this method what you need to perform
} else {
Toast.makeText(this, "Need permission ON.", Toast.LENGTH_SHORT).show();
}
4: Now implement onRequestPermissionsResult() method in your Activity as below
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case Utility.MY_PERMISSIONS_REQUEST:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (userChoosenTask.equals("STORAGE"))
performTaskOperation();//this method what you need to perform
}
break;
}
}
I just use an array to achieved multiple requests, hope it helps someone. (Kotlin)
// got all permission
private fun requestPermission(){
var mIndex: Int = -1
var requestList: Array<String> = Array(10, { "" } )
// phone call Permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.CALL_PHONE
}
// SMS Permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.SEND_SMS
}
// Access photos Permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.READ_EXTERNAL_STORAGE
}
// Location Permission
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.ACCESS_FINE_LOCATION
}
if(mIndex != -1){
ActivityCompat.requestPermissions(this, requestList, PERMISSIONS_REQUEST_ALL)
}
}
// permission response
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
PERMISSIONS_REQUEST_ALL -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Phone Call permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "SMS permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "SMS permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Location permission accept.")
}
} else {
Toast.makeText(mContext, "Permission Failed!", Toast.LENGTH_LONG).show()
}
return
}
}
}
I found this is in the runtime permissions example from Google's github.
private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS};
private static final int REQUEST_CONTACTS = 1;
ActivityCompat.requestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
Check the "Asking for multiple permissions at a time" section in this article:
Things you need to know about Android M permissions
It's very well explained, and may also touch other related topics you haven't think about.
Use helper like this (permissions names do not matter).
public class MyPermission {
private static final int PERMISSION_REQUEST_ALL = 127;
private MainActivity mMainActivity;
MyPermission(MainActivity mainActivity) {
mMainActivity = mainActivity;
}
public static boolean hasPermission(String permission, Context context) {
if (isNewPermissionModel()) {
return (ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}
return true;
}
private static boolean hasPermissions(Context context, String... permissions) {
if (isNewPermissionModel() && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
private static boolean shouldShowRationale(Activity activity, String permission) {
return isNewPermissionModel() && ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
private static boolean isNewPermissionModel() {
return VERSION.SDK_INT > VERSION_CODES.LOLLIPOP_MR1;
}
/**
* check all permissions
*/
void checkAll() {
//check dangerous permissions, make request if need (Android will ask only for the ones it needs)
String[] PERMISSIONS = {
permission.READ_CALENDAR,
permission.ACCESS_COARSE_LOCATION
};
if (!hasPermissions(mMainActivity, PERMISSIONS)) {
ActivityCompat.requestPermissions(mMainActivity, PERMISSIONS, PERMISSION_REQUEST_ALL);
}
}
void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_ALL) {
if (grantResults.length > 0) {
//for not granted
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equals(permission.READ_CALENDAR)) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
smartRequestPermissions(permission.READ_CALENDAR, R.string.permission_required_dialog_read_calendar);
}
} else if (permissions[i].equals(permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
smartRequestPermissions(permission.ACCESS_COARSE_LOCATION, R.string.permission_required_dialog_access_coarse_location);
}
}
}
}
}
}
private void smartRequestPermissions(final String permissionName, int permissionRequiredDialog) {
if (shouldShowRationale(mMainActivity, permissionName)) {// If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false.
//Show an explanation to the user with action
mMainActivity.mSnackProgressBarManager.show(
new SnackProgressBar(
SnackProgressBar.TYPE_ACTION, mMainActivity.getString(permissionRequiredDialog)
)
.setAction("OK", new OnActionClickListener() {
#Override
public void onActionClick() {
checkAll();
}
})
.setSwipeToDismiss(true).setAllowUserInput(true)
, MainActivity.SNACKBAR_WARNING_DURATION
);
} // else do nothing
}
}
Simple way to ask multiple permission,
https://github.com/sachinvarma/EasyPermission
How to add :
repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
How to ask permission:
List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);
new EasyPermissionInit(MainActivity.this, permission);
For more Details - >
https://github.com/sachinvarma/EasyPermission/blob/master/app/src/main/java/com/sachinvarma/easypermissionsample/MainActivity.java
It may help someone in future.
In Kotlin:
private val id = 1
private val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION)
fun hasPermissions(): Boolean {
for (perm in permissions) {
if (ActivityCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
return false
}
}
return true
}
if(! hasPermissions()){
requestPermissions(this, permissions, id)
}
This is what I have done in my activity. Hoping will be helpful. I am asking for camera and microphone permissions.
public class ActiveCallActivity extends AppCompatActivity {
.....
private static final String cameraPermissionKey = "cameraPermission";
private static final String microphonePermissionkey = "microphonePermission";
private static ArrayList<String> permissionsQueue = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.....
// in ValidationCheckersAndValidators simply checking if have permission or not.
if(ValidationCheckersAndValidators.haveCameraPermission(this)) performHaveCameraPermissionLayout(); else performHaveNoCameraPermissionLayout();
if(ValidationCheckersAndValidators.haveMicrophonePermission(this)) performHaveMicrophonePermissionLayout(); else performHaveNoMicrophonePermissionLayout();
}
private void performHaveNoCameraPermissionLayout() {
.....
permissionsQueue.add(cameraPermissionKey);
}
private void performHaveNoMicrophonePermissionLayout() {
.....
permissionsQueue.add(microphonePermissionkey);
}
#Override
protected void onResume() {
super.onResume();
.....
passThroughPermissionsQueue();
}
private void passThroughPermissionsQueue() {
if(!permissionsQueue.isEmpty()) {
String permissionKey = permissionsQueue.remove(0);
switch (permissionKey) {
case cameraPermissionKey: {
ValidationCheckersAndValidators.requestForCameraPermission(this);
return;
}
case microphonePermissionkey: {
ValidationCheckersAndValidators.requestForMicrophonePermission(this);
return;
}
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch(requestCode) {
case cameraPermissionRequestCode: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
performHaveCameraPermissionLayout();
}
break;
}
case microphonePermissionRequestCode: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
performHaveMicrophonePermissionLayout();
}
break;
}
}
passThroughPermissionsQueue();
}
}
You can use Dexter
In build.gradle add:
implementation 'com.karumi:dexter:5.0.0'
And use it in your activity as:
val requiredPermissions = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> listOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
else -> listOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION)
}
Dexter.withActivity(this)
.withPermissions(
requiredPermissions
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
/* ... */
}
override fun onPermissionsChecked(report: MultiplePermissionsReport) =
if (report.isAnyPermissionPermanentlyDenied) {
toast("You should grant all permissions")
} else {
toast("All permissions granted")
// continue here if permission is a must
}).check()
// continue here if permission is not a must
In my app, I need GPS to locate the user. I wish my app provide following kinds of result.
1.The current location.(Success)
2.Failed to get current location because of device error or something else. (Failed)
3.The user refused the permission. (Permission denied)
I use LocationManager to do the job.
locationManager = (LocationManager)mActivity.getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
If the permission is denied, the location will be null.
But I don't know what the location will be if the function failed. And I 'm not sure whether that location is null and user refuse to open GPS are equal.
With the following code, I might know whether the permission is added in the AndroidManifest.xml. But I can't get the information I need.
boolean getLocationOn = (PackageManager.PERMISSION_GRANTED ==
pm.checkPermission("android.permission.ACCESS_FINE_LOCATION", "my_package"));
Use below code to check and request permission
private void checkAndRequestPermissions() {
int camera = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
int storage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int loc = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION);
int loc2 = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
int logs = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_LOGS);
int networkstate = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_NETWORK_STATE);
int internet = ContextCompat.checkSelfPermission(this, android.Manifest.permission.INTERNET);
int wifistate = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_WIFI_STATE);
int externalstorage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
int phonestate = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE);
int wakelock = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WAKE_LOCK);
int alarm = ContextCompat.checkSelfPermission(this, android.Manifest.permission.SET_ALARM);
int audio = ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO);
int accounts = ContextCompat.checkSelfPermission(this, android.Manifest.permission.GET_ACCOUNTS);
int contacts = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.CAMERA);
}
if (storage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (loc2 != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
}
if (loc != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (logs != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.READ_LOGS);
}
if (networkstate != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_NETWORK_STATE);
}
if (internet != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.INTERNET);
}
if (wifistate != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_WIFI_STATE);
}
if (externalstorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (phonestate != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.READ_PHONE_STATE);
}
if (wakelock != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.WAKE_LOCK);
}
if (alarm != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SET_ALARM);
}
if (audio != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.RECORD_AUDIO);
}
if (accounts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.GET_ACCOUNTS);
}
if (contacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.READ_CONTACTS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
}
}
Call checkAndRequestPermissions() to check and request for permission.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkAndRequestPermissions();
}
Create a method to check permissions.
public static final int MULTIPLE_PERMISSIONS = 15;
String[] permissions= new String[]
{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
};
Below function will request for permissions.
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == MULTIPLE_PERMISSIONS) {
Log.v("Nopermissionz", "No permission granted , " + permissions.length);
if (permissions.length == 2
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.v("Nopermission1", "Permission granted , " + permissions.length);
} else {
Log.v("Nopermission2", "No permission granted");
Snackbar.make(findViewById(android.R.id.content), "Please allow this App with some permissions", Snackbar.LENGTH_INDEFINITE)
.setAction("SETTINGS", new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.show();
}
}
}
Call the method checkPermissions() to check if permissions are granted.
private boolean checkPermissions()
{
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions)
{
result = ContextCompat.checkSelfPermission(MainActivity.this,p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(MainActivity.this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
return false;
}
return true;
}
First implement an onRequestPermissionResult like this:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_ACCESS_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, do your stuff!
locationManager = (LocationManager)mActivity.getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
} else {
//location wasn't found
}
} else {
//user denied permission additionally you can check
//ActivityCompat.shouldShowRequestPermissionRationale if user checked on "do not show again" while clicking deny
}
return;
}
}
}
In onCreate()of my activity I check for permissions.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
}
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CHECK_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
}
For every permission,in its callback method I perform certain tasks.So I cannot ask the permissions in array like
String[] permissions { };
as it will provide me only one call back for all permissions.I perform tasks in every callback in following way.
case ConstantClass.READ_PERMISSION:
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
doSomething();
Toast.makeText(MainActivity.this, getResources().getString(R.string.Cannot_Vibrate_Phone), Toast.LENGTH_LONG).show();
}
break;
case ConstantClass.CALL_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
dialPhoneNumber();
} else {
Toast.makeText(MainActivity.this, getString(R.string.permission_access_call), Toast.LENGTH_LONG).show();
}
break;
If I ask these permissions one after other in onCreate(). Only the first permission is displayed.So I get only one call back working. So how to achieve the scenario that for every single permission I get a separate call back and call some functions in them.
Thank you :)
Check this Demo Code
Ask next permission in response of first permission reject/grant in
onRequestPermissionsResult()
public class MainActivity extends Activity {
private Context context;
private static final int REQUEST_RUNTIME_PERMISSION_1 = 111;
private static final int REQUEST_RUNTIME_PERMISSION_2 = 222;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
if (CheckPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// you have permission go ahead
} else {
// you do not have permission go request runtime permissions
RequestPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_RUNTIME_PERMISSION_1);
}
}
#Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions,
int[] grantResults) {
switch (permsRequestCode) {
case REQUEST_RUNTIME_PERMISSION_1: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// you have permission go ahead ask next permission and get separate callback
RequestPermission(MainActivity.this, Manifest.permission.CAMERA, REQUEST_RUNTIME_PERMISSION_2);
} else {
// you do not have permission show toast.
/*check your logic ask again*/
//RequestPermission(MainActivity.this, Manifest.permission.CAMERA, REQUEST_RUNTIME_PERMISSION_2);
}
return;
}
case REQUEST_RUNTIME_PERMISSION_2: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// you have 2nd permission go ahead
} else {
// you do not have 2nd permission show toast.
}
return;
}
}
}
public void RequestPermission(Activity thisActivity, String Permission, int Code) {
if (ContextCompat.checkSelfPermission(thisActivity,
Permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Permission)) {
} else {
ActivityCompat.requestPermissions(thisActivity,
new String[]{Permission},
Code);
}
}
}
public boolean CheckPermission(Context context, String Permission) {
if (ContextCompat.checkSelfPermission(context,
Permission) == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
}
You can ask the next permission in onRequestPermission to show permission request one after another. You can examine the below code and get the idea. In onRequestPermissionResult method:
case ConstantClass.READ_PERMISSION:
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
doSomething();
Toast.makeText(MainActivity.this, getResources().getString(R.string.Cannot_Vibrate_Phone), Toast.LENGTH_LONG).show();
}
// Ask for Camera permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CHECK_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
break;
Hope this helps.
String permissions[] = new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.INTERNET};
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
&&ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&&ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ){
ActivityCompat.requestPermissions(this, permissions, ALL_REQUEST_CODE);
}
else if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&&ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[] {permissions[1], permissions[2], permissions[3]}, ALL_REQUEST_CODE);
}
else if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[] {permissions[2], permissions[3]}, ALL_REQUEST_CODE);
}
This is the best way to get permissions
i am taking runtime permission from user by using below code in fragment .
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_PERMISSION_CODE);
}
and overriding
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 21: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
but override method not called
please give me hint for that i have to override in fragment
Use FragmentCompat instead of ActivityCompat.
Becouse remember for futher u must do this in ACTIVITY not in a fragment. Yoou can d this tricky in fragment but this is bad way
this is in Activity. I check permissions and save it
private static final int REQUEST_CODE_GET_ACCOUNTS = 101;
private static final int REQUEST_AUDIO_PERMISSION = 102;
#TargetApi(23)
public void checkAudioPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
playerFragment.setupVisualizerFxAndUI();
return;
}
if (this.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager
.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},
REQUEST_AUDIO_PERMISSION);
} else {
playerFragment.setupVisualizerFxAndUI();
}
}
#TargetApi(23)
public void checkGmailPermission() {
if (isDeviceOnline()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
showGmailRecFragment(true);
return;
}
if (this.checkSelfPermission(Manifest.permission.GET_ACCOUNTS) != PackageManager
.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.GET_ACCOUNTS},
REQUEST_CODE_GET_ACCOUNTS);
return;
} else {
showGmailRecFragment(true);
}
} else {
Utils.showToast(this, getString(R.string.no_internet));
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
grantResults) {
switch (requestCode) {
case REQUEST_CODE_GET_ACCOUNTS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showGmailRecFragment(true);
} else {
Utils.showToast(this, getString(R.string.accounts_permision_denied));
}
break;
case REQUEST_AUDIO_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
playerFragment.setupVisualizerFxAndUI();
} else {
Utils.showToast(this, getString(R.string.audio_permission_denied));
}
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
and this is on fragment when i want check permission again or if user denied it. Also this save the permissions
private void setupViewVisualizer() {
if (!isLiveTv && !homeVideo.isVideoType()) {
((PlayerActivity) activity).checkAudioPermission();
} else {
return;
}
}
Use this code for Fragment
private void requestReadExternalStorageCameraPermission() {
if (FragmentCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
Toast.show(getActivity(), getString(R.string.toast_permission), Toast.ToastType.ALERT);
} else {
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE_CAMERA);
}
}
and
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE_GALLARY:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
captureImageInitialization(1);
}
break;
case PERMISSION_REQUEST_CODE_CAMERA:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
captureImageInitialization(0);
}
break;
default:
break;
}
}
Try this..
private static final int REQUEST_RUNTIME_PERMISSION = 123;
if (CheckPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
// you have permission go ahead
} else {
// you do not have permission go request runtime permissions
RequestPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE, REQUEST_RUNTIME_PERMISSION);
}
#Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
switch (permsRequestCode) {
case REQUEST_RUNTIME_PERMISSION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
// you do not have permission show toast.
}
return;
}
}
}
public void RequestPermission(Activity thisActivity, String Permission, int Code) {
if (ContextCompat.checkSelfPermission(thisActivity,
Permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Permission)) {
} else {
ActivityCompat.requestPermissions(thisActivity,
new String[]{Permission},
Code);
}
}
}
public boolean CheckPermission(Activity context, String Permission) {
if (ContextCompat.checkSelfPermission(context,
Permission) == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
I had the same issue,
It is a common mistake and it is very simple to solve.
if you are in an activity we normally use
ActivityCompat.requestPermissions(activity, permissionsNeeded.toTypedArray(),PERMISSION_REQUEST_CODE)
But you shouldn't use the same for a fragment. You can simply use it like requestPermissions(permissionsNeeded.toTypedArray(),PERMISSION_REQUEST_CODE)
If you call the Activity.requestPermission in fragment, the on request callback is get called in the Activity not in the Fragment.
Happy coding
when Request for Permission from fragment
Kotlin
requireActivity().requestPermissions(<Permission array>, <Request code>)
Java
getActivity().requestPermissions(<Permission array>, <Request code>)
You can call fragment onRequestPermissionsResult from activity's onRequestPermissionsResult
Kotlin
var fragments:List? = supportFragmentManager.fragments
var lastFragment:Fragment? = if(fragments!=null && fragments.size>0) fragments.get(fragments.size-1) else null
var lastFragmentName:String? = if(lastFragment!=null) lastFragment.javaClass.name else ""
if (lastFragmentName.equals("com.example.YourFragment")){
lastFragment?.onRequestPermissionsResult(requestCode,permissions,grantResults)
}
Java
List fragments = getSupportFragmentManager().getFragments();
Fragment lastFragment = (fragments!=null && fragments.size()>0)?fragments.get(fragments.size()-1) : null;
String lastFragmentName = (lastFragment!=null) ? lastFragment.getClass().getName() : "";
if (lastFragment!=null && lastFragmentName.equals("com.example.YourFragment")){
lastFragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
To handle permissions in a Fragment call requestPermissions method. If you override onRequestPermissionsResult method in both fragment and activity, containing that fragment, make sure to call super.onRequestPermissionsResult(...) in the activity method to propagate call to the onRequestPermissionsResult method in the fragment.