Understanding the Android 6 permission method

后端 未结 3 2174
眼角桃花
眼角桃花 2021-01-18 21:25

I am trying to take an image from Gallery and set it to an imageview but in Android 6 there are some permission problems. Below is the method to ask for the permission. Shou

相关标签:
3条回答
  • 2021-01-18 22:12

    So I have completely rewritten the code to request permissions. Now it supports requesting for multiple permissions and running code with proper result. Also it works with preMarshmallow devices, so you don't have to check and copy the code in that case.

    First, create an Activity class with this code (You can extend any king of activity you need, e.g. 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 Activities and Fragments should extend these classes instead of the standart ones.

    Now you are ready to request the permissions by calling a method:

    requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
    

    If the permission is required for the app to work, you should call this method and specify the message saying why the permission is required.

    requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
    

    DONT MISSCALL THE DEFAULT METHOD, WHICH IS

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

    Here is the example of requesting contacts:

    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 the PermissionListener, don't forget to return true when the requestCode is the correct one, otherwise the PermissionListener won't be removed from the ArrayList and you'll most likely get a small memory leak.

    0 讨论(0)
  • 2021-01-18 22:16

    EDIT

    I have rewritted the code and posted in another answer.

    Old answer:

    Yes, you have to check and ask for permission every time.

    Usually I write the code like this:

    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 it is not a best way, but at least it gives a possibility to request permission and make actions easier.

    0 讨论(0)
  • 2021-01-18 22:25

    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 for device and Request for permissions

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

    Check Permission is 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 permissions onRequestPermissionsResult

     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 讨论(0)
提交回复
热议问题