Understanding Android 6 Resolution Method

I'm trying to take an image from the gallery and set it to an image, but on Android 6 there are some resolution problems. The following is the permission request method. Should I request read external storage or write external storage?

Here is what I have done so far:

private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1; public void getPermissionToReadExternalStorage() { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (shouldShowRequestPermissionRationale( Manifest.permission.READ_EXTERNAL_STORAGE)) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, READ_CONTACTS_PERMISSIONS_REQUEST); }}} @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults){ // Make sure it our original READ_CONTACTS request if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } 

Now my click listener selects data from the gallery:

  pro.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); if (android.os.Build.VERSION.SDK_INT >= 23) { getPermissionToReadExternalStorage(); if (getPermissionToReadExternalStorage () this???? <==) startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0); } else { startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0); }} }); return v; } 

Now I want to get the result of the getPermissionToReadExternalStorage() method so that I can run the Activity to select the gallery for Android 6. How can I get the result of the void class? And one more thing - do I need to write a method for each permission my application requests?

+5
source share
3 answers

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

 // DON'T USE THIS ONE! requestPermissions(String[] requestPermissions, int requestCode) // DON'T USE THIS ONE! 

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.

+6
source

EDIT

I rewrote the code and sent in a different answer.

Old answer:

Yes, you must check and request permission each time.

I usually write code as follows:

 private int requestPermissionCode; private Runnable requestPermissionRunnable; private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) { if (android.os.Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissionCode = requestCode; requestPermissionRunnable = codeToRun; requestPermissions(new String[]{requestPermission}, requestCode); } } else { codeToRun.run(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { if (requestCode == requestPermissionCode) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestPermissionRunnable != null) requestPermissionRunnable.run(); } else { Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } 

and run it like this:

  runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() { @Override public void run() { // your code here } }); 

I am sure that this is not the best way, but at least it makes it possible to request permission and make the actions easier.

0
source

Initialize Your Permission

 private static final int INITIAL_REQUEST = 1337; private static final int GET_ACCOUNTS = INITIAL_REQUEST+2; private static final int LOCATION_REQUEST =INITIAL_REQUEST+3; private static final String[] INITIAL_PERMS = { Manifest.permission.GET_ACCOUNTS, Manifest.permission.INTERNET, Manifest.permission.ACCESS_FINE_LOCATION }; 

Check device availability and permission request

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) { requestPermissions(INITIAL_PERMS, INITIAL_REQUEST); } } 

Check permission granted Or not

 private boolean canAccessAccounts() { return (hasPermission(Manifest.permission.GET_ACCOUNTS)); } private boolean canAccessLocation() { return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)); } private boolean canAccessInternet() { return (hasPermission(Manifest.permission.INTERNET)); } private boolean hasPermission(String perm) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm)); } return (true); } 

Update permissions and check method for onRequestPermissionsResult permissions

  void UpdatePermissions(){ canAccessInternet(); canAccessLocation(); canAccessInternet(); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { UpdatePermissions(); switch(requestCode) { case GET_ACCOUNTS: if (canAccessAccounts()) { } else { } break; case LOCATION_REQUEST: if (canAccessLocation()) { } else { } break; case INITIAL_REQUEST: if(canAccessInternet()){ }else { } break; } } 
0
source

Source: https://habr.com/ru/post/1237882/


All Articles