• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

onRequestPermissionsResult() not called for AppCompatActivity

Hi,
I have a simple app for my android 7.0 test device (LG G6) that presses a button called Scan that activates the ZXing Barcode scanner implemented in my app build.gradle:

Code:
implementation 'com.journeyapps:zxing-android-embedded:3.0.2@aar'
implementation 'com.google.zxing:core:3.2.0'

But before that I needed to get permission from the user to activate the camera for the app, so I have the Manifest.xml listing the permission required:

Code:
<uses-permission android:name="android.permission.CAMERA" />,

Next I have the MainActivity activity that extends AppCompartActivity implements OnClickListener for the scan button click event:

Code:
public class MainActivity extends AppCompatActivity implements OnClickListener {
..
}

I have a permission request code in my class declarations as well as a global boolean to determine if I have permission.

Code:
private static final int MY_PERMISSIONS_REQUEST_CAMERA = 100;
private boolean cameraPermissionGranted = false;

Then in my onClick() I check for the scan button click, then the permission check

Code:
@override
public void onClick(View v) {
    //scan
    if(v.getId()==R.id.scan_button){

        boolean bHasPermission = false;

        // Here, this is the current activity
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
        {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA))
            {
                if (TextUtils.isEmpty("")) {
                    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA );
                }
                else{
                    // Show rationale message
                }
            }
            else
            {
                ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA );
                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }
        else{
            cameraPermissionGranted = true;
        }

        if (cameraPermissionGranted)
        {
            // Already have permission
            IntentIntegrator scanIntegrator = new IntentIntegrator(this);

            scanIntegrator.initiateScan();
            // Results of the scan are then retrieved via the onActivityResult callback method below
        }
    }
}

I then have a onRequestPermissionsResult() callback which should be called when I use ActivityCompat.requestPermission() and set cameraPermissionGranted, but it is ignored completely.

Code:
@override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_CAMERA: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                cameraPermissionGranted = true;
            } else {
                cameraPermissionGranted =false;
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request.
    }
}

I am not using Fragments so I shouldn't need to reference requestPermissions() without ActivityCompat, nor can I as I get an error when I take it off.

So why am I not able to override the onRequestPermissionResult() method?
 
Last edited:
The first thing to do is verify that requestPermissions() is called. Set a breakpoint at the start of the onClick() method, and step through the code.
 
The first thing to do is verify that requestPermissions() is called. Set a breakpoint at the start of the onClick() method, and step through the code.
requestPermissions is called and I get the permissions prompt on my phone after I resume debugging, but when I select Allow/Deny the callback is not triggered and it passes through to the if (cameraPermissionGranted) check without a value given to it from the callback.
 
Ah, it is being called but when I step over the .requestPermissions() function my line of code reaches the cameraPermissionGranted check but my user has yet to select anything from the prompted permission check on the screen so it's too late to change the variable value and needs to wait for the 2nd scan button click before permission is accepted from a 2nd late permissions request pop-up.
 
You're misunderstanding how the callback pattern works. The call to requestPermission() is asynchronous. That means it runs in a separate thread, and the code after this call is executed immediately, even before the callback is executed.
Did you put a breakpoint in onRequestPermissionsResult() to verify that this method is called?
 
Ah, it is being called but when I step over the .requestPermissions() function my line of code reaches the cameraPermissionGranted check but my user has yet to select anything from the prompted permission check on the screen so it's too late to change the variable value and needs to wait for the 2nd scan button click before permission is accepted from a 2nd late permissions request pop-up.

You got it! Asynchronous execution, not synchronous.
 
So how do I delay the code from getting to the cameraPermissionGranted check until after the user has selected the permission the first time?
 
So how do I delay the code from getting to the cameraPermissionGranted check until after the user has selected the permission the first time?

You don't. Any checking can only be done in the onRequestPermissionsResult() method, or after it's been called. Think about it - the only way your app can know if the permission's been granted, is after the user dialog has been shown, and the user has responded. Only then does your onRequestPermissionsResult() method get called. Until that happens, you just don't know if the user has granted permission, or not.
 
Okay makes sense, is there a way to activate the onClick() method again from the callback so I can go directly I to my scanner with the correct permission values, or do I make the user click the scan button a 2nd time after granting permission?
 
Is there any reason why you can't put the initiateScan() code in the onRequestPermissionsResult() method?
 
I was hoping I wouldn't have to and that the scanner would only be activated from the onClick() and not in any other location, but I have now added a function that creates my scan integrator and referenced the method call from both the onClick (with permission granted result only) and from the permission result callback upon a granted permission value.

This now works in both cases now, so thanks for the help!
 
Back
Top Bottom