You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:37:48