2015-10-28 3 views
3

Заметьте, что я говорю о Android Lollipop. Для android 6.0 мы можем использовать метод canDrawOverlays(), чтобы удостовериться, что SYSTEM_ALERT_WINDOW предоставляется или нет.Как проверить разрешение SYSTEM_ALERT_WINDOW предоставляется на Android Lollipop?

С Android Lollipop почти все устройства предоставляют это разрешение по умолчанию. Но на некоторых устройствах Xiaomi, Meizu .. это не предоставляется. Пользователи должны перейти в информацию о приложении, чтобы это разрешить.

Как мы можем проверить это программно, чтобы предупредить пользователей?

ответ

4

в MIUI использовать

public static boolean isMiuiFloatWindowOpAllowed(@NonNull Context context) { 
    final int version = Build.VERSION.SDK_INT; 

    if (version >= 19) { 
     return checkOp(context, OP_SYSTEM_ALERT_WINDOW); //See AppOpsManager.OP_SYSTEM_ALERT_WINDOW=24 /*@hide/ 
    } else { 
     return (context.getApplicationInfo().flags & 1<<27) == 1; 
    } 
} 

public static boolean checkOp(Context context, int op, String packageName, int uid) { 
    final int version = Build.VERSION.SDK_INT; 

    if (version >= 19) { 
     AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 
     try { 
      return (AppOpsManager.MODE_ALLOWED == (Integer) ReflectUtils.invokeMethod(manager, "checkOp", op, uid, packageName)); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } else { 
     Flog.e("Below API 19 cannot invoke!"); 
    } 
    return false; 
} 

ReflectUtils.java

public static Object invokeMethod(@NonNull Object receiver, String methodName, Object... methodArgs) throws Exception { 
    Class<?>[] argsClass = null; 
    if (methodArgs != null && methodArgs.length != 0) { 
     int length = methodArgs.length; 
     argsClass = new Class[length]; 
     for (int i=0; i<length; i++) { 
      argsClass[i] = getBaseTypeClass(methodArgs[i].getClass()); 
     } 
    } 

    Method method = receiver.getClass().getMethod(methodName, argsClass); 
    return method.invoke(receiver, methodArgs); 
} 
+0

спасибо! Я попробую! – TOP

+0

Где я могу получить OP_SYSTEM_ALERT_WINDOW? что такое uid? – TOP

+0

И я не могу найти 'ReflectUtils'. Где я могу получить это? – TOP

1

Отражение рискованно, потому что вы берете вещи как должное ... и все может измениться в будущих версиях Android. Следующий метод использует отражение только в том случае, если правильный путь не выполняется.

@SuppressLint("NewApi") 
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; } 

} 
+0

получение AppOpsManager.MODE_IGNORED или значение 1 в xiaomi note3. Нужны дальнейшие предложения. – UMESH0492

+0

Тогда у вас нет разрешения .... просите об этом: Intent intent = new Intent (Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse ("package:" + act.getPackageName())); startActivityForResult (намерение, requestCode); – Anonymous

+0

возвращает android.content.ActivityNotFoundException: Не найдено действий для обработки Intent {act = android.settings.action.MANAGE_OVERLAY_PERMISSION dat = package: com.findmeout.android} – UMESH0492