Android Oreo中显示弹窗时出现BadTokenException问题求助
修复Android Oreo中悬浮窗BadTokenException问题
我来帮你解决这个问题~Android Oreo(API 26)开始,系统对悬浮窗的权限和窗口类型做了严格限制,你遇到的BadTokenException(提示"token null is not valid; is your activity running?")主要是这几个原因导致的:窗口类型未适配Oreo、缺少悬浮窗权限,或者弹窗显示时机不当。下面是具体的修复方案:
1. 适配Oreo及以上的窗口类型
Oreo不再允许普通应用使用TYPE_PHONE或TYPE_SYSTEM_ALERT这类系统级窗口类型,必须改用TYPE_APPLICATION_OVERLAY。低版本可以保留原有类型,做版本判断即可:
int windowType; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Oreo及以上使用应用覆盖层类型 windowType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { // 低版本保留原有类型 windowType = WindowManager.LayoutParams.TYPE_PHONE; } // 创建WindowManager参数时使用适配后的类型 WindowManager.LayoutParams params = new WindowManager.LayoutParams( screen[0], screen[1], windowType, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
2. 动态申请悬浮窗权限
Oreo及以上需要用户手动授予悬浮窗权限(属于特殊权限,Manifest声明无效),显示弹窗前必须先检查权限:
权限检查方法
private boolean hasOverlayPermission(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return Settings.canDrawOverlays(context); } // 6.0以下无需权限 return true; }
申请权限逻辑
在显示VideoToneView前调用以下代码,引导用户开启权限:
if (!hasOverlayPermission(getContext())) { Intent permissionIntent = new Intent( Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()) ); // 如果是在Activity中,直接startActivityForResult;如果是View类,需要传Activity的Context启动 ((Activity) getContext()).startActivityForResult(permissionIntent, 1001); return; } // 权限已授予,再执行添加窗口的逻辑
3. 确保弹窗显示时机正确
错误提示中的token null可能是因为弹窗显示时Activity已经销毁,或者使用了无效的Context。建议:
- 避免在Activity的
onDestroy、onStop之后尝试显示弹窗; - 显示前检查Activity状态:
Activity activity = (Activity) getContext(); if (activity.isFinishing() || activity.isDestroyed()) { // Activity已不可用,不要显示弹窗 return; } - 尽量使用当前活跃Activity的Context,而非Application Context(虽然Oreo+允许用Application Context,但需要权限且更容易出现token问题)。
4. 检查WindowToken设置
如果你的悬浮窗是依附于Activity的弹窗,确保设置正确的WindowToken:
// 使用Activity的DecorView的token,避免null params.token = ((Activity) getContext()).getWindow().getDecorView().getWindowToken();
如果是全局悬浮窗(不依附Activity),Oreo+下使用TYPE_APPLICATION_OVERLAY时可以不用设置token,但必须确保已获取悬浮窗权限。
按照以上步骤修改后,应该就能解决Oreo及以上版本的BadTokenException问题啦~
内容的提问来源于stack exchange,提问作者Asqa
相关产品推荐
相关产品推荐

