add window android.view.ViewRootImpl$W@fa525bc -- permission denied for window type 2003

问题详情: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了,第一次入坑,记录一下。

猜你喜欢

转载自blog.csdn.net/lyh1299259684/article/details/80768672