So, I completely rewrote the code to request permissions. Now it supports a request for multiple permissions and code execution with the correct result. It also works with preMarshmallow devices, so you do not need to check and copy the code in this case.
First create an Activity class with this code (you can extend any activity king you need, for example AppCompatActivity):
public abstract class PermissionActivity extends AppCompatActivity { private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>(); @SuppressWarnings("unused") public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) { requestPermissions(requestCode, requestPermissions, null, permissionListener); } @SuppressWarnings("unused") public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) { final int[] grantResults = new int[requestPermissions.length]; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ArrayList<String> list_notGranted = new ArrayList<>(); for (String requestPermission : requestPermissions) if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED) list_notGranted.add(requestPermission); if (list_notGranted.size() > 0) { permissionListeners.add(permissionListener); requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]); if (message != null) { boolean shouldShowRequestPermissionRationale = false; for (String permission : requestPermissions) if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { shouldShowRequestPermissionRationale = true; break; } if (shouldShowRequestPermissionRationale) { final String[] f_requestPermissions = requestPermissions; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(message); DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() { @TargetApi(Build.VERSION_CODES.M) @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode); break; default: for (int i = 0; i < grantResults.length; i++) grantResults[i] = PackageManager.PERMISSION_DENIED; if (permissionListener != null) permissionListener.onResult(requestCode, f_requestPermissions, grantResults); break; } } }; builder.setPositiveButton("OK", onClickListener); builder.setNegativeButton("Cancel", onClickListener); builder.show(); } else { super.requestPermissions(requestPermissions, requestCode); } } else { super.requestPermissions(requestPermissions, requestCode); } } else { for (int i = 0; i < grantResults.length; i++) grantResults[i] = PackageManager.PERMISSION_GRANTED; if (permissionListener != null) permissionListener.onResult(requestCode, requestPermissions, grantResults); } } else { if (permissionListener != null) { for (int i = 0; i < grantResults.length; i++) grantResults[i] = PackageManager.PERMISSION_GRANTED; permissionListener.onResult(requestCode, requestPermissions, grantResults); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) { PermissionListener permissionListener = it.next(); if (permissionListener.onResult(requestCode, permissions, grantResults)) { it.remove(); } } } public interface PermissionListener { boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults); } }
If you want to request permissions from Fragments, add this class:
public class PermissionFragment extends Fragment { @SuppressWarnings("unused") public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) { requestPermissions(requestCode, requestPermissions, null, permissionListener); } @SuppressWarnings("unused") public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) { ((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener); } }
Your actions and fragments should extend these classes instead of the standard ones.
Now you are ready to request permission by calling the method:
requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
If permission is required for the application to work, you must call this method and provide a message indicating why permission is required.
requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
DO NOT ALLOW THE DEFAULT METHOD WHICH
Here is an example contact request:
private void requestAndLoadContacts() { String[] permissions = new String[]{Manifest.permission.READ_CONTACTS}; requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() { @Override public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) { // Check if the requestCode is ours if (requestCode == REQUEST_PERMISSIONS_CONTACTS) { // Check if the permission is correct and is granted if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted // Calling a method to actually load the contacts loadContacts(); } else { // Permission not granted Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show(); } return true; } return false; } }); }
Note: When you implement a PermissionListener, be sure to return true when the requestCode is correct , otherwise the PermissionListener will not be removed from the ArrayList, and you are likely to get a small memory leak.