Android悬浮窗权限问题
一、悬浮窗适配的两种方法:
1、按照正规的流程,如果系统没有赋予 APP 弹出悬浮窗的权限,就先跳转到权限授权界面,等用户打开该权限之后,再去弹出悬浮窗,比如 QQ 等一些主流应用就是这么做得;
2、利用系统的漏洞,绕过权限的申请,简单粗暴;不建议使用,因为兼容性有待商榷。
3、大脑模糊区域:悬浮窗与对话框权限是不同的,是不一样的。
二、不同系统版本之间的差异(以正规流程申请权限)
1、API 19之前:
- 直接调用 WindowManager 的 addView 方法弹出即可。
- 由于判断权限的类 AppOpsManager 是 API19 版本添加,所以Android 4.4 之前的版本(不包括4.4)就不用去判断了。
2、Android 4.4 ~ Android 5.1.1:(需要引导用户手动打开申请权限)
- 由于碎片化程度比较大,所以需要针对特定机型进行适配
- 主要问题在于,如何检测出不同产商的ROM,不同产商的ROM如何引导用户手动打开申请权限,可参考博客(http://blog.csdn.net/self_study/article/details/52859790)
- 各ROM版本,通用检查悬浮窗权限方法
//OP_SYSTEM_ALERT_WINDOW = 24;
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
3、Android 6.0:
- 悬浮窗权限在 6.0 之后就被 google 单独拿出来管理了,因此在所有手机和 6.0 以及之后的版本上适配的方法都是一样的
- 在 AndroidManifest.xml中静态申请
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- 在使用时先判断该权限是否已经被授权,如果没有授权使用下面这段代码进行动态申请:
// 检查是否已经申请了 权限
if (Build.VERSION.SDK_INT >= 23) {
try {
Class clazz = Settings.class;
Method canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
result = (Boolean) canDrawOverlays.invoke(null, context);
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
// 跳转到设置页面,引导用户手动打开申请权限
try {
Class clazz = Settings.class;
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
Intent intent = new Intent(field.get(null).toString());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
} catch (Exception e) {
}