1

In my app, I am requesting permission in the onCreate() function like this

if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED)
            registerListener(context);
        else if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.ACTIVITY_RECOGNITION))
            new AlertDialog.Builder(context)
                    .setTitle("Permission required")
                    .setMessage("This permission is required to fetch the sensor data from your phone, denying it will cause the app to exit")
                    .setPositiveButton("Give permission", (dialog, which) -> ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, ACTIVITY_REQUEST_CODE))
                    .setNegativeButton("Deny", (dialog, which) -> ((Activity) context).finish())
                    .show();
        else
            ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, ACTIVITY_REQUEST_CODE);

And this is the onRequestPermissionsResult overriden method

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == presenter.ACTIVITY_REQUEST_CODE)
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                presenter.registerListener(this);
            else {
                Toast.makeText(this, "Permission denied, exiting", Toast.LENGTH_LONG).show();
                finish();
            }
    }

Now the issue I am facing is I get the proper popup to ask the permission but I see the toast message (Permission denied, exiting) BEFORE I even make a choice and because of the finish() method call the app exits BEFORE I make the choice!

I have no clue why this is happening, any help is appreciated!

Mihir Kandoi
  • 101
  • 1
  • 10

4 Answers4

0

Actually onRequestPermissionsResult is getting called perfectly as expected. You have to handle the case inside it's body. Your problem is Activity gets finished before dialog opens to make any choice. So, just try commenting out finish() method inside onRequestPermissionsResult. Look at below code for better clarity.

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == presenter.ACTIVITY_REQUEST_CODE)
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            presenter.registerListener(this);
        else {
            // if user denies permission then Dialog would be pop up. That's why I commented out both toast and finish() method below.
            // If user clicks deny on the dialog then only finish activity.
            //Toast.makeText(this, "Permission denied, exiting", Toast.LENGTH_LONG).show();
            //finish();
        }
}

Handle user denial case at below part of your code:

.setNegativeButton("Deny", (dialog, which) -> {
                        // Put code here for user denial------
                        finish();
                    })
NRUSINGHA MOHARANA
  • 1,489
  • 8
  • 13
0

Solution is here

Use Dexter to make your life easier

(1) Add the following dependency in your build.grade (app level) file

implementation ‘com.karumi:dexter:6.2.2’

(2) Now just use it..

 Dexter.withActivity(this)
                // below line is use to request the number of 
                // permissions which are required in our app.
                .withPermissions(Manifest.permission.CAMERA,
                        // below is the list of permissions
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.READ_CONTACTS)
                // after adding permissions we are 
                // calling an with listener method.
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
                        // this method is called when all permissions are granted
                        if (multiplePermissionsReport.areAllPermissionsGranted()) {
                            // do you work now
                            Toast.makeText(MainActivity.this, "All the permissions are granted..", Toast.LENGTH_SHORT).show();
                        }
                        // check for permanent denial of any permission
                        if (multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
                            // permission is denied permanently,
                            // we will show user a dialog message.
                            showSettingsDialog();
                        }
                    }
  
                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> list, PermissionToken permissionToken) {
                        // this method is called when user grants some 
                        // permission and denies some of them.
                        permissionToken.continuePermissionRequest();
                    }
                }).withErrorListener(new PermissionRequestErrorListener() {
            // this method is use to handle error 
            // in runtime permissions
            @Override
            public void onError(DexterError error) {
                // we are displaying a toast message for error message.
                Toast.makeText(getApplicationContext(), "Error occurred! ", Toast.LENGTH_SHORT).show();
            }
        })
                // below line is use to run the permissions
                // on same thread and to check the permissions
                .onSameThread().check();`
Kamal Nayan
  • 1,635
  • 1
  • 5
  • 19
  • It's a very small project though, if nothing works I will definitely use this but do you have any idea why is the permission result method being called TWICE? – Mihir Kandoi Apr 24 '21 at 10:12
  • Sorry, I generally use dexter so I don't have the idea. And by using dexter your work will be hassle-free so move to it. – Kamal Nayan Apr 24 '21 at 10:18
0

I'll suggest rather than creating a Dialog, Let Android make it up for you. Check whether permission s given or not

private boolean checkRECOGNITIONPermission(){
        final boolean isReturn = ContextCompat.checkSelfPermission
                     (this, Manifest.permission.Manifest.permission.ACTIVITY_RECOGNITION)
                           == PackageManager.PERMISSION_GRANTED;
        return isReturn;
    }

Then request permission

private void requestStoragePermissionExport(){     
      ActivityCompat.requestPermissions
     (this,new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, ACTIVITY_REQUEST_CODE);
 }

Check whether Permission granted or not

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        // handle permission request
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case ACTIVITY_REQUEST_CODE : 
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    // permission granted do your work
                    
                }else {
                    Toast.makeText(this, Permission Required, Toast.LENGTH_SHORT).show();
                }
                break;          
            }
        }

and call this when you want to check for permission

if(checkRECOGNITIONPermission()){
   // Do work (Permission granted)
}else{
   checkRECOGNITIONPermission(); // request permission
   if(!checkRECOGNITIONPermission()){
       finsih();
   }
}
Swapnil Padaya
  • 687
  • 5
  • 14
0

This looks like the result of the user having previously been presented with the request for permission but clicking Deny.

In that case, a call to ActivityCompat.requestPermissions will not display Android's own Dialog and, even worse, onRequestPermissionsResult will be called anyway, even though the documentation says it is only called in response to user input (or at least I haven't seen anything official to say otherwise).

Also worse, your code won't be able to prompt the user again to change the permission to Allow - this can only be done by going to the Settings app.

It looks like you then need to pick up the 'Deny' action in the onRequestPermissionsResult method and then create a dialog to tell the user to go to Settings and start again.

I think the rationale is to not pester the user with prompts when they have denied permission, but to call onRequestPermissionsResult and dump you in the 'Denied' section, however since you're likely to want to throw up a Dialog saying the app is likely of little use, it kind of defeats the purpose.

See also this other answer:

https://stackoverflow.com/a/48301505/1038479

Mitch
  • 1,017
  • 1
  • 13
  • 25