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

后端 未结 10 657
萌比男神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

    SO FINALLY MY TIME HAS COME TO ANSWER A QUESTION FROM COMMONSWARE


    Business flow:-

    1. When user clicks on "deny permission" for the first time, I will show rationale dialog to explain the necessity of the permission. Then if the user clicks on "cancel" button on the rationale dialog, I will show a toast showing message "Please give permission to get location".

    2. After that when user clicks on deny permission(dont ask again) on the permissions dialog, I will show a message "Please give location permission from app settings". Notice that I have added the words "from app settings" because the user has checked the box of "dont ask again".

    3. So from now on the permission dialog will not be shown.Also the rationale dialog will not be shown.

    So the key here is that if both permission dialog and rationale dialog is not shown, then it means that user has checked the "dont ask again" checkbox.

    The code:-

            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)){
                    AlertDialogHelper.showDialogWithYesNoCallback(mContext, getString(R.string.confirm), getString(R.string.please_give_permission_to_get_location), new onItemClickReturnBoolean() {
                        @Override
                        public void onItemClick(Boolean status) {
                            if(status){
                                ActivityCompat.requestPermissions(SplashScreenActivity.this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
                            }
                            else{
                                ShowToast.showShortToast(SplashScreenActivity.this,getString(R.string.please_give_permission_to_get_location));
                                finish();
                            }
                        }
                    });
                }
                else{
                    ActivityCompat.requestPermissions(this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
                }
            }
            else{
                gettingLocationAfterPermissionGranted();
            }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if(requestCode == AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE){
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    gettingLocationAfterPermissionGranted();
                }
                else{
                    if(ActivityCompat.shouldShowRequestPermissionRationale(SplashScreenActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)){
                        ShowToast.showShortToast(this,getString(R.string.please_give_permission_to_get_location));
                    }
                    else{
                        ShowToast.showShortToast(this,getString(R.string.please_give_location_permission_from_app_settings));
                    }
                    finish();
                }
            }
        }
    

    Check this repository: https://github.com/debChowdhury/PermissionHelperEasy


    Easy peasy


    0 讨论(0)
  • 2020-11-28 21:18

    After trying all the answer here and some other post over internet. I came to know that I have to use a sharedPreference isLocationPermissionDialogShown (default false) and every thing works as per expected.

    1. If first time asked for permission. In this case shouldShowRequestPermissionRationale returns false and isLocationPermissionDialogShown also false
    2. Second time shouldShowRequestPermissionRationale return true and while showing dialog we set isLocationPermissionDialogShown to true. and when we check condition both will be true
    3. Every Time until Never Ask Again ticked shouldShowRequestPermissionRationale return true and isLocationPermissionDialogShown returns true
    4. If Never Ask Again ticked shouldShowRequestPermissionRationale return false and isLocationPermissionDialogShown returns true. Which is what we need.

    Please check working example.

    public class MainActivity extends AppCompatActivity {
        SharedPreferences sharedPreferences;
        String locationPermission;
        String prefLocationPermissionKey = "isLocationPermissionDialogShown";
        private final int PERMISSION_REQUEST_CODE_LOCATION = 1001;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            locationPermission = Manifest.permission.ACCESS_FINE_LOCATION;
            sharedPreferences = getSharedPreferences("configuration", MODE_PRIVATE);
    
            //check for android version
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                //Check for permission
                if (checkSelfPermission(locationPermission) != PackageManager.PERMISSION_GRANTED) {
                    //check if clarification dialog should be shown.
                    if (shouldShowRequestPermissionRationale(locationPermission)) {
                        showClarificationDialog(locationPermission, PERMISSION_REQUEST_CODE_LOCATION);
                    } else  {
                        requestPermissions(new String[] { locationPermission}, PERMISSION_REQUEST_CODE_LOCATION);
                    }
                } else {
                    Log.d("nets-debug", "permission already grranted");
                }
            }
    
        }
    
        @Override
        @TargetApi(Build.VERSION_CODES.M)
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    
            if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                //for location permission
                if (requestCode == PERMISSION_REQUEST_CODE_LOCATION) {
                    boolean isLocationPermissionDialogShown = sharedPreferences.getBoolean(prefLocationPermissionKey, false);
    
                    if (!shouldShowRequestPermissionRationale(locationPermission) && isLocationPermissionDialogShown) {
                        // user selected Never Ask Again. do something
                        Log.d("nets-debug", "never ask again");
                    } else {
                        // all other conditions like first time asked, previously denied etc are captured here and can be extended if required.
                        Log.d("nets-debug", "all other cases");
                    }
                }
    
            }
    
        }
    
        @TargetApi(Build.VERSION_CODES.M)
        public void showClarificationDialog(final String permission, final int requestCode) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Permission Required");
            builder.setMessage("Please grant Location permission to use all features of this app");
            builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putBoolean(prefLocationPermissionKey, true);
                    editor.apply();
                    requestPermissions(new String[] {permission}, requestCode);
                }
            });
            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(getApplicationContext(), "This permission required", Toast.LENGTH_LONG).show();
                }
            });
            builder.create().show();
        }
    
    }
    

    Hope this will help.

    0 讨论(0)
  • 2020-11-28 21:20

    As per the current example: https://github.com/googlesamples/android-RuntimePermissions/blob/master/Application/src/main/java/com/example/android/system/runtimepermissions/MainActivity.java#L195

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
            int[] grantResults) {
        if (requestCode == REQUEST_CAMERA) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                doThing();
                //STORE FALSE IN SHAREDPREFERENCES
            } else {
                //STORE TRUE IN SHAREDPREFERENCES
            }
        }
    

    Store a boolean in SharedPreferences with key as your permission code and value as indicated above, to indicate whether that preference has been denied before.

    Sadly, you probably can't check against a preference that has been accepted and later denied while your app is running. The final spec is not available, but there's a chance that your app either gets restarted or gets mock values until the next launch.

    0 讨论(0)
  • 2020-11-28 21:28

    You can look here - there is a flowchart that explains the process quite good. It also explains when you should call shouldShowRequestPermissionRationale() and when it returns true.

    Basically according to Android's documentation, you should always ask for permission if you don't have it (Android will automatically return DENIED in the callback if the user said to never ask again) and you should display a short message if the user has already declined you once in the past but hasn't marked the never ask again option.

    0 讨论(0)
提交回复
热议问题