在4.4的系统上,部分恶心的系统诸如X米等可以直接在应用管理中将部分权限关闭,下面以SYSTEM_ALERT_WINDOW为例,在系统中判断当前对应权限是否已经打开。
4.4上新增加了一个类 android.app.AppOpsManager 来对一些应用操作方法进行了一些封装,而我们今天只是需要检查悬浮窗权限是否有开而已。
查看代码,找到checkOp方法,这个就是检查对应的权限有没有打开的方法。1
2
3
4
5
6
7
8
9
10
11public int checkOp(int op, int uid, String packageName) {
try {
int mode = mService.checkOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
}
return MODE_IGNORED;
}
第一个参数指的是需要检查的操作ID,其也是宝义在这个类的 OP_* 的常量中,而今天需要需要检查的悬浮窗操作数就是1
2/** @hide */
public static final int OP_SYSTEM_ALERT_WINDOW = 24;
是的,这是隐藏的。
第二个参数是调用这个方法的应用的uid。
第三个就是需要查询的包名。
以下为检查的方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 (Build.VERSION_CODES.KITKAT)
public static boolean isFloatAllowed(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
try {
checkOp(context, 24); // OP_SYSTEM_ALERT_WINDOW = 24
} catch (Exception e) {
e.printStackTrace();
}
} else {
if ((context.getApplicationInfo().flags & 1 << 27) == 1) {
return true;
} else {
return false;
}
}
return false;
}
(Build.VERSION_CODES.KITKAT)
public static boolean checkOp(Context context, int op) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
final int version = Build.VERSION.SDK_INT;
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 });
int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { op, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });
if (mode != AppOpsManager.MODE_ALLOWED) {
//disabled
return false;
} else {
//enabled
return true;
}
}
以上方法为4.4可用。