How Do We Distinguish Never-Asked From Stop-Asking in Android M's Runtime Permissions?

后端 未结 10 682
萌比男神i
萌比男神i 2020-11-28 20:48

When it comes to the M Developer Preview runtime permissions, according to Google:

  1. If you have never asked for a certain permission before, just ask for it<

10条回答
  •  天涯浪人
    2020-11-28 21:17

    I know I am posting very late, but detailed example may be helpful for someone.

    What I have noticed is, if we check the shouldShowRequestPermissionRationale() flag in to onRequestPermissionsResult() callback method, it shows only two states.

    State 1:-Return true:-- Any time user clicks Deny permissions (including the very first time.

    State 2:-Returns false :- if user select s “never asks again.

    Here is an example with multiple permission request:-

    The app needs 2 permissions at startup . SEND_SMS and ACCESS_FINE_LOCATION (both are mentioned in manifest.xml).

    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 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;
    }
    

    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 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();
        }
    

提交回复
热议问题