Settings.canDrawOverlays возвращает false даже после включения разрешения из настроек
Я пытаюсь проверить код из этого ответа, чтобы проверить, включено ли разрешение. но он возвращает false, даже если разрешение включено в настройках.
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; }
}
4 ответа
Недавно я также столкнулся с той же проблемой и получил следующий обходной путь. Ссылка с https://code.google.com/p/android/issues/detail?id=198671
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;
}
Проверка включает в себя администратора устройства? Я столкнулся с этой проблемой при отключении администратора устройства, я проверил это разрешение в DeviceAdminReceiver->onDisabled() и на некоторых устройствах, и canDrawOverlays вернул false, несмотря на то, что у меня было разрешение.
Приведенный выше ответ помог иногда, но не всегда. то, что сработало, это Thread.sleep перед проверкой.
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// some exception here
}
Минимальное время, которое работало для меня, было 20 миллис. чем canDrawOverlays вернул true
Примечание: это не очень хорошая практика, но это единственное, что сработало для меня
Я попытался возобновить действие после того, как пользователь получил доступ к настройке. Это код:
public static void restartActivity (Activity act) {
Intent intent = getIntent ();
Конец();
startActivity (намерение);
}
Основываясь на ответе BennyP, я заставил Runnable запустить необходимый код через 500 мс, и это сработало очень хорошо. Обратная связь немного задерживается, но пользователь даже не заметит задержку.
Это код, который я добавил в свой 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);
Надеюсь, поможет!
Прежде всего, я действительно очень удивлен этим странным поведением
Settings.canDrawOverlays(this);
Я также столкнулся с той же проблемой с его использованием, он возвращал false, даже если разрешение уже назначено. Что я заметил, я использовал эту проверку в моем методе onStart(), где он создавал это проводное поведение. Чтобы решить эту проблему, я искал через Интернет, и не было никакого результата, который мог бы удовлетворить меня и тот, который я могу использовать.
Решение
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);
}
}
Я сделал что-то подобное в моем onCreate(). Здесь я соответственно сохранил значения в моих SharedPreferences, и в соответствии с этими значениями Shared Preference я создал проверку для отображения диалогового окна наложения в моем onStart(). Это работало нормально!
Вы можете попробовать это решение и пометить этот ответ как полезный, если ваша проблема решена.
Спасибо