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

Xamarin Forms Android应用中ConnectivityManager无法检测重试/取消对话框取消按钮点击的问题

解决方案:拦截系统WiFi连接对话框的取消事件

看起来你遇到的是系统级对话框的交互拦截问题——那个自动弹出的第二个对话框是Android系统在网络连接请求失败时展示的默认提示,咱们没法直接通过NetworkCallback捕获它的取消点击事件,因为系统并没有把这个操作传递给咱们的回调。下面给你几个可行的解决思路,按推荐程度排序:

1. 替换系统对话框,自定义全流程UI(最推荐)

既然系统对话框不受咱们控制,那不如把整个网络检测和连接的UI逻辑收回到自己手里,完全避免系统弹出默认对话框:

  • 提前扫描并验证目标网络:在调用ConnectivityManager.RequestNetwork()之前,先用WifiManager主动扫描WiFi网络,检查目标SSID是否存在于扫描结果中。
    var wifiManager = (WifiManager)Android.App.Application.Context.GetSystemService(Context.WifiService);
    // 启动扫描(需要ACCESS_FINE_LOCATION和CHANGE_WIFI_STATE权限)
    wifiManager.StartScan();
    // 获取扫描结果
    var scanResults = wifiManager.ScanResults;
    bool targetNetworkExists = scanResults.Any(result => result.Ssid == "你的目标SSID");
    
    if (!targetNetworkExists)
    {
        // 弹出你自己的自定义对话框,提示用户网络未找到
        var alertDialog = new AlertDialog.Builder(Context)
            .SetTitle("网络未找到")
            .SetMessage("无法检测到目标WiFi网络,请重试")
            .SetPositiveButton("重试", (s, e) => { /* 重新执行扫描/连接逻辑 */ })
            .SetNegativeButton("Cancella", (s, e) => { 
                // 在这里直接处理用户取消的逻辑,比如清理网络请求、更新UI
                connectivityManager.UnregisterNetworkCallback(networkCallback);
                // 执行你原本想在OnUnavailable里做的操作
            })
            .Create();
        alertDialog.Show();
        return;
    }
    
  • 这样用户所有的操作都在你的自定义UI里,取消事件完全可控,还能给用户更统一的App体验。

2. 用AccessibilityService监听系统对话框(备选,需要用户授权)

如果必须保留系统对话框,可以通过Android的辅助功能服务来监听系统弹窗的交互:

  • 创建一个继承自AccessibilityService的类,在OnAccessibilityEvent方法里监听对话框的出现,识别出那个带有“Cancella”按钮的系统对话框:
    public class WifiDialogAccessibilityService : AccessibilityService
    {
        public override void OnAccessibilityEvent(AccessibilityEvent e)
        {
            if (e.EventType == EventTypes.WindowStateChanged && e.PackageName == "com.android.settings")
            {
                // 判断对话框是否是WiFi连接相关的(可以通过窗口标题或文本判断)
                var nodeInfo = RootInActiveWindow;
                if (nodeInfo != null)
                {
                    var cancelButton = FindNodeByText(nodeInfo, "Cancella");
                    if (cancelButton != null && cancelButton.IsClickable)
                    {
                        // 当用户点击取消按钮时,发送广播或直接通知你的主应用
                        var intent = new Intent("WIFI_CONNECTION_CANCELLED");
                        SendBroadcast(intent);
                    }
                }
            }
        }
    
        private AccessibilityNodeInfo FindNodeByText(AccessibilityNodeInfo root, string text)
        {
            if (root == null) return null;
            for (int i = 0; i < root.ChildCount; i++)
            {
                var child = root.GetChild(i);
                if (child != null && child.Text == text)
                {
                    return child;
                }
                var found = FindNodeByText(child, text);
                if (found != null) return found;
            }
            return null;
        }
    
        public override void OnInterrupt() { }
    }
    
  • 然后在你的主Activity里注册广播接收器,收到“WIFI_CONNECTION_CANCELLED”广播时,执行取消后的逻辑(比如注销NetworkCallback、清理资源)。
  • 注意:这种方式需要用户在系统设置里给你的App开启辅助功能权限,体验上会有额外步骤,所以只推荐作为备选方案。

3. 结合超时机制补全回调逻辑(简单应急方案)

如果上面两种方案都暂时没法实现,可以给网络请求加个超时定时器:

  • 在调用ConnectivityManager.RequestNetwork()的时候,启动一个延迟任务,比如等待10秒,如果这段时间内OnAvailable或OnUnavailable都没被触发,就默认认为用户取消了操作:
    // 发起网络请求
    connectivityManager.RequestNetwork(networkRequest, networkCallback);
    
    // 启动超时任务
    _ = Task.Delay(10000).ContinueWith(t =>
    {
        if (!_isNetworkConnected) // 用一个变量标记是否已经成功连接
        {
            // 执行取消后的逻辑
            connectivityManager.UnregisterNetworkCallback(networkCallback);
            // 更新UI或通知用户
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
    
  • 记得在OnAvailable里把_isNetworkConnected设为true,避免超时任务误触发。

额外注意事项

  • 确保你已经申请了必要的权限:ACCESS_FINE_LOCATION、CHANGE_WIFI_STATE、ACCESS_NETWORK_STATE,并且在Android 6+上请求了动态权限,否则WiFi扫描会失败。
  • 无论用哪种方案,都要记得在页面销毁或不再需要时调用ConnectivityManager.UnregisterNetworkCallback(),避免内存泄漏。

内容的提问来源于stack exchange,提问作者giani.sim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:33:12