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

AlertDialog报错:Unable to add window -- token null无效,活动是否运行?

解决Android 7.0部分设备AlertDialog抛出"token null is not valid"问题

我之前碰到过好几次这种三星7.0设备上的AlertDialog令牌问题,核心根源是部分定制ROM对Activity窗口生命周期的管理逻辑和原生Android有差异,导致调用Show()时Activity的窗口令牌还没准备好,或者已经失效。结合你的Xamarin场景,给你几个靠谱的解决方向:

1. 确保调用Show()时Activity处于活跃状态

很多时候这个错误是因为在Activity还没完全启动(比如OnCreate/OnStart阶段)或者已经开始销毁时调用了Show()。你可以在调用前增加状态检查:

// 检查Activity是否未销毁且未进入结束流程
if (!this.IsFinishing && !this.IsDestroyed)
{
    yourCustomAlertDialog.Show();
}

如果是在异步回调或者广播里调用,建议延迟到Activity的OnResume之后执行,比如用PostDelayed确保窗口初始化完成:

this.RunOnUiThread(() =>
{
    new Handler().PostDelayed(() => 
    {
        if (!IsFinishing && !IsDestroyed)
        {
            yourCustomAlertDialog.Show();
        }
    }, 200); // 短延迟适配部分设备的窗口初始化速度
});

2. 绝对不要用ApplicationContext创建AlertDialog

AlertDialog是依附于Activity窗口的控件,必须传入当前Activity的Context实例,而不能用Application.Context——因为ApplicationContext没有自己的窗口令牌,在部分严格的ROM里直接就会报错。确保你的Dialog构造代码是这样的:

// 正确:传入当前Activity实例(this代表当前Activity)
var dialogBuilder = new AlertDialog.Builder(this);
// 错误:不要用Application.Context
// var dialogBuilder = new AlertDialog.Builder(Application.Context);

3. 针对三星ROM的特殊窗口类型适配

部分三星7.0设备对系统级窗口的权限检查更严格,你可以尝试给AlertDialog设置合适的窗口类型,同时申请对应权限:

第一步:添加权限到AndroidManifest.xml

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

第二步:动态申请权限(Android 6.0+)

if (Build.VERSION.SdkInt >= BuildVersionCodes.M && !Settings.CanDrawOverlays(this))
{
    // 引导用户开启悬浮窗权限
    Intent overlayPermissionIntent = new Intent(
        Settings.ActionManageOverlayPermission,
        Android.Net.Uri.Parse($"package:{PackageName}")
    );
    StartActivityForResult(overlayPermissionIntent, 1001);
}

第三步:设置窗口类型

var dialog = dialogBuilder.Create();
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
    // Android 8.0+用TYPE_APPLICATION_OVERLAY
    dialog.Window.SetType(WindowManagerTypes.ApplicationOverlay);
}
else
{
    // 低版本用TYPE_SYSTEM_ALERT
    dialog.Window.SetType(WindowManagerTypes.SystemAlert);
}
// 再设置顶部显示的布局参数
dialog.Window.SetGravity(GravityFlags.Top);
dialog.Window.SetLayout(WindowManagerLayoutParams.MatchParent, WindowManagerLayoutParams.WrapContent);

4. 改用DialogFragment(最推荐的方案)

AlertDialog本身和Activity生命周期的绑定不够严谨,而DialogFragment是Google官方推荐的弹窗实现,会自动跟随Activity的生命周期,从根源上避免令牌无效的问题。Xamarin中实现起来也很简单:

自定义DialogFragment类

public class TopNotificationDialog : DialogFragment
{
    public override Dialog OnCreateDialog(Bundle savedInstanceState)
    {
        // 在这里构建你的自定义弹窗内容
        return new AlertDialog.Builder(Activity)
            .SetTitle("顶部通知")
            .SetMessage("你的自定义通知内容")
            .SetPositiveButton("确定", (s, e) => Dismiss())
            .Create();
    }

    public override void OnStart()
    {
        base.OnStart();
        // 设置弹窗显示在顶部
        if (Dialog != null && Dialog.Window != null)
        {
            var windowParams = Dialog.Window.Attributes;
            windowParams.Gravity = GravityFlags.Top;
            windowParams.Width = WindowManagerLayoutParams.MatchParent;
            Dialog.Window.Attributes = windowParams;
        }
    }
}

调用弹窗

// 确保Activity处于活跃状态时调用
if (!IsFinishing && !IsDestroyed)
{
    var dialogFragment = new TopNotificationDialog();
    dialogFragment.Show(SupportFragmentManager, "TopNotificationTag");
}

以上几个方案里,优先推荐用DialogFragment,它的适配性和生命周期管理是最稳定的,能解决绝大多数跨设备的弹窗问题。

内容的提问来源于stack exchange,提问作者Anees Deen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:43:36