问题详情:android.view.WindowManager$BadTokenException
Unable to add window android.view.ViewRootImpl$W@fa525bc -- permission denied for window type 2003
先说下这个坑出现的原因吧,这个问题经测试只有在Android8.0才会出现,所以这个问题出现的原因是我们没有悬浮窗权限以及指定的WindowManager窗口类型有误。
这里要解释一下:Android 8.0我们要弹出一个Dialog时,不要设置
WindowManager.LayoutParams.Type为WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
而是要设置为:WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
代码如下:
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
lp.width = (int) (display.getWidth() - width); //设置宽度
//窗口类型
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
dialog.getWindow().setAttributes(lp);
dialog.show();
故:我们要在设置窗口类型的时候判断是否为8.0及以上系统,然后进行不同的设置。
注意:设置窗口类型一定要在Dialog调用show()方法之前。
此外,我们还需要在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
如果是Android 8.0系统,需要我们动态授权悬浮窗权限,代码如下:
@TargetApi(Build.VERSION_CODES.O)
protected boolean requestDrawOverLays() {
if (!Settings.canDrawOverlays(mContext)) {
showMsg("使用本应用需要您开启悬浮窗权限,请前往设置。");
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + mContext.getPackageName()));
startActivityForResult(intent, Constant.OVERLAY_PERMISSION_REQ_CODE);
return false;
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Constant.OVERLAY_PERMISSION_REQ_CODE:
if (requestDrawOverLays()) {
//允许悬浮窗
}
break;
}
}
到此已经OK了,第一次入坑,记录一下。