Settings.canDrawOverlays is returning false even after turning the permission on from settings

孤人 提交于 2019-12-10 15:22:47

问题


I am trying billow Code from this answer to check if the permission is enabled. but it is returning false even when the permission is enabled from the settings.

public static boolean canDrawOverlayViews(Context con){
    if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
    try {
        return Settings.canDrawOverlays(con);
    }
    catch(NoSuchMethodError e){
        return canDrawOverlaysUsingReflection(con);
    }
}


public static boolean canDrawOverlaysUsingReflection(Context context) {

    try {

        AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        Class clazz = AppOpsManager.class;
        Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
        //AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
        int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });

        return AppOpsManager.MODE_ALLOWED == mode;

    } catch (Exception e) {  return false;  }

}

回答1:


Recently I've also faced the same issue and got the following workaround . Referenced from https://code.google.com/p/android/issues/detail?id=198671#c7

public boolean getWindoOverLayAddedOrNot2() {

   String sClassName = "android.provider.Settings";
   try {
       Class classToInvestigate = Class.forName(sClassName);
       if (context == null)
           context = activity;
       Method method = classToInvestigate.getDeclaredMethod("isCallingPackageAllowedToDrawOverlays", Context.class, int.class, String.class, boolean.class);
       Object value = method.invoke(null, context, Process.myUid(), context.getPackageName(), false);

       Log.i("Tag", value.toString());
       // Dynamically do stuff with this class
       // List constructors, fields, methods, etc.

   } catch (ClassNotFoundException e) {
       // Class not found!
   } catch (Exception e) {
       // Unknown exception
       e.printStackTrace();
   }

   return false;
}



回答2:


does the check involves the device admin? I have encountered this problem when disabling device admin, I have checked this permission in the DeviceAdminReceiver->onDisabled() and on some devices, and canDrawOverlays returned false, despite the fact i had the permission.

The above answer helped sometimes but not all the time. the thing that did work is Thread.sleep before the check.

try {
    Thread.sleep(20);
} catch (InterruptedException e) {
    // some exception here
}

The minimal time that worked for me was 20 millis. than canDrawOverlays returned true

Note: this is not a good practice however this is the only thing that worked for me




回答3:


Based on BennyP's answer, I've made a Runnable run the required code after 500ms and that worked very well. The feedback is a bit delayed, but the user won't even notice the delay.

This is the code I've added to my onResume()

Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(!Settings.canDrawOverlays(ControllerActivity.this)){
                //Handle overlay permission not given here
            }
            else{
                //Handle overlay permission given here
            }
        }
    }, 500);

Hope it helps!




回答4:


I tried restarting the activity after the user accessed the setting . This is code :

public static void restartActivity(Activity act){

Intent intent = getIntent();

finish();

startActivity(intent);

}




回答5:


First of all, I am really very surprised with this strange behaviour of

    Settings.canDrawOverlays(this);        

I also faced the same issue with its usage, it was returning false even if the permission is already assigned. What I noticed that, I was using this check in my onStart() method, where it was creating this wired behavior. To resolve this, I searched over internet and no result was there that can satisfy me and the one I can use.

Solution

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        Log.e("Overlay Permission", "" + Settings.canDrawOverlays(this));
        if (!Settings.canDrawOverlays(this)) {
            MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", true);
        } else {
            MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", false);
        }
    }

I did something lake this, in my onCreate(). Here I saved the values accordingly in my SharedPreferences, and according to these Shared Preference values, I created a check for showing an overlay dialog in my onStart(). This worked fine!

You can try this solution, and mark this answer useful if your problem is solved.

Thanks



来源:https://stackoverflow.com/questions/39852569/settings-candrawoverlays-is-returning-false-even-after-turning-the-permission-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!