【Android】Caused by: android.view.WindowManager$BadTokenException

在适配Android8.0+之前,应用内使用系统级的弹框:

//manifest
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />


//java
IconTextDialog iconTextDialog = new IconTextDialog(context, context.getResources().getString(R.string.iscontinue), R.drawable.ic_popup_icon_error, leaveDialogListener);
iconTextDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);//重点
show(iconTextDialog);

运行在Android8.1设备上报错:

System.err: Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@cd9c6dc -- permission denied for window type 2003
System.err:     at android.view.ViewRootImpl.setView(ViewRootImpl.java:789)
System.err:     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
System.err:     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
System.err:     at android.app.Dialog.show(Dialog.java:330)

怎么处理?

这是因为在Android8.0+的系统中,Google规定申请"android.permission.SYSTEM_ALERT_WINDOW"权限的应用,需要给悬浮窗口设置Type: WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY.如下:

IconTextDialog iconTextDialog = new IconTextDialog(context.getApplicationContext(), context.getResources().getString(R.string.iscontinue), R.drawable.ic_popup_icon_error, leaveDialogListener);
//iconTextDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);//这里换掉了
iconTextDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);//这里换掉了
show(iconTextDialog);

但,申请"android.permission.SYSTEM_ALERT_WINDOW"权限,需要使用如下方式:

private final int REQUEST_SYSTEM_ALERT_WINDOW = 10068;//自定义
        
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_SYSTEM_ALERT_WINDOW);

之后在,onActivityResut中获取权限授权结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_SYSTEM_ALERT_WINDOW:
            //TODO 验证权限是否申请成功,并进行下一步
            break;
    }
}

还有其他情况么?

  1. 引用了错误的context : 在一个普通的应用内Dialog中,使用了applicationContext,换个activity的context吧。
  2. 发生在内存泄漏时 :context溢出了,所以在Activity销毁前,要正确关闭弹窗才行。
  3. PopupWindow在Activity的onCreate()中就调用了show,需要等待Activity控件渲染完毕再调用。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值