-->

Android 6 revoked permissions checked as granted

2020-08-08 00:54发布

问题:

Got a problem hat I'm not sure is a bug or not.

If the user grants a permission and then subsequently revokes it, it appears that checkSelfPermission returns GRANTED on the revoked permission.

e.g. it appears that after revoking permission.CAMERA:

true == ActivityCompat.checkSelfPermission(context, permission.CAMERA)
                            == PackageManager.PERMISSION_GRANTED

The only way i seem to find out that camera was revoked is by an exception:

10-20 14:25:54.330: E/AndroidRuntime(13954): java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE flg=0x3 cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity clip={text/uri-list U:file:///storage/emulated/0/Pictures/JPEG_20151020_142554_399504353.jpg} (has extras) } from ProcessRecord{adc5d77 13954:com.conx2share.conx2share.staging/u0a144} (pid=13954, uid=10144) with revoked permission android.permission.CAMERA
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.os.Parcel.readException(Parcel.java:1599)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.os.Parcel.readException(Parcel.java:1552)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2658)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.app.Activity.startActivityForResult(Activity.java:3917)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.app.Activity.startActivityForResult(Activity.java:3877)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:855)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.support.v4.app.FragmentActivity$HostCallbacks.onStartActivityFromFragment(FragmentActivity.java:907)
10-20 14:25:54.330: E/AndroidRuntime(13954):    at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:930)

Does anyone know if this is user error or a bug in the new permissions system?

回答1:

I'm a little late to the party, but I just had this problem and think should be useful to someone else in the future.

According to Google link https://developers.google.com/android/guides/permissions#prerequisites

Along with new platform features, Android 6.0 Marshmallow has a new permissions model that streamlines the app install and auto-update process. Permissions are now requested at runtime instead of before app installation.

So, if you are targeting your app to SDK level 23 or greater, permissions declared in AndroidManifest.xml are not enough (though necessary). Ensure that you are using the V4 support library and do the check as shown below:

@Override
    public void onClick(View view) {

        // Check permission for CAMERA
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            // Check Permissions Now
            // Callback onRequestPermissionsResult interceptado na Activity MainActivity
            ActivityCompat.requestPermissions(getActivity(),
                                              new String[]{Manifest.permission.CAMERA},
                                              MainActivity.REQUEST_CAMERA);
        } else {
            // permission has been granted, continue as usual

            Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(captureIntent, 0);
        }

In my case, i did the check on a Fragment, but could be done in an Activity, it depends on your needs.

The user can grant permission to the app by going to Settings > Apps > yourapp and then grant the permission. In that case, the logic goes by the else and the intent is called. In the other hand, the life is not so easy and the user won't do that. Therefore we have to call ActivityCompat.requestPermissions:

ActivityCompat.requestPermissions(getActivity(),
                                              new String[]{Manifest.permission.CAMERA},
                                              MainActivity.REQUEST_CAMERA);

In the first parameter I passed getActivity() because I am using a Fragment. If you are using Activity, pass this. The second parameter is the permission to be checked and the third is an app-defined int constant to be used as an identifier into the callback method that I will explain next.

public static final int REQUEST_CAMERA = 1;

ActivityCompat.requestPermissions will open a dialog asking the user to grant or deny the permission. That's why we have to use the method onRequestPermissionsResult:

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CAMERA: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_SHORT).show();
                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(getApplicationContext(), "Permission denied", Toast.LENGTH_SHORT).show();
                }
                return;
            }

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

In case you are using Fragment, like me, this callback method have to be in the Activity that contains the Fragment.



回答2:

This turns out to have been a programmer error in the logic.