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

Xamarin Android获取WiFi列表失败求助(Android 10+)

Xamarin Android 10+ 无法获取WiFi列表的问题排查与修复

针对你在树莓派Android 10+环境下无法获取WiFi列表的问题,核心原因是Android 10及以上版本对WiFi扫描和权限做了严格限制,你的代码未适配这些新规则,以下是具体问题和修复方案:

1. 权限不足与权限申请缺失

Android 10(API 29)及更高版本要求:

  • 必须拥有ACCESS_FINE_LOCATION前台权限(ACCESS_COARSE_LOCATION不再满足WiFi扫描要求)
  • Android 12(API 31)及以上还需添加NEARBY_WIFI_DEVICES权限
  • 权限必须主动向用户申请,仅在Manifest声明无效

修复:

第一步:更新AndroidManifest.xml

添加NEARBY_WIFI_DEVICES权限,并为位置权限补充前台属性:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:foregroundServiceType="location" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" />
<!-- 保留原有必要权限 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

第二步:在调用扫描前主动申请权限

修改MainPage.xaml.cs的btn1_Clicked方法,先完成权限校验再执行扫描:

private async void btn1_Clicked(object sender, EventArgs e)
{
    // 申请位置权限
    var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
    if (status != PermissionStatus.Granted)
    {
        status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
        if (status != PermissionStatus.Granted)
        {
            txtlog.Text = "权限未授予,无法获取WiFi列表";
            return;
        }
    }

    // 检查位置服务是否开启(Android 10+必须开启才能扫描WiFi)
    var locationEnabled = await Geolocation.IsLocationAvailableAsync();
    if (!locationEnabled)
    {
        txtlog.Text = "请开启位置服务后重试";
        await App.Current.MainPage.DisplayAlert("提示", "需要开启位置服务才能获取WiFi列表", "去设置");
        // 可选:跳转到位置设置页
        // Android.App.Application.Context.StartActivity(new Android.Content.Intent(Android.Provider.Settings.ActionLocationSourceSettings));
        return;
    }

    // 执行WiFi扫描
    try
    {
        IEnumerable<string> _wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
        // 过滤空SSID并去重
        var uniqueWifis = _wifiService.Where(s => !string.IsNullOrEmpty(s)).Distinct().ToList();
        txtlog.Text = $"找到{uniqueWifis.Count}个WiFi网络";
        wifilist.ItemsSource = uniqueWifis;
    }
    catch (Exception ex)
    {
        txtlog.Text = $"扫描失败:{ex.Message}";
    }
}

2. 广播接收器未注销导致异常

你的代码注册了广播接收器,但未在扫描完成或超时后注销,会引发内存泄漏,甚至导致后续扫描失败。

修复:

修改Wifi类的GetAvailableNetworksAsync方法,确保接收器被注销:

public async Task<IEnumerable<string>> GetAvailableNetworksAsync()
{
    var wifiMgr = (WifiManager)context.GetSystemService(Context.WifiService);
    var wifiReceiver = new WifiReceiver(wifiMgr);
    var intentFilter = new IntentFilter(WifiManager.ScanResultsAvailableAction);
    
    try
    {
        context.RegisterReceiver(wifiReceiver, intentFilter);
        return await Task.Run(() => wifiReceiver.Scan());
    }
    finally
    {
        // 无论成功失败,强制注销接收器
        try
        {
            context.UnregisterReceiver(wifiReceiver);
        }
        catch { } // 忽略注销失败的情况
    }
}

3. WiFi扫描的前台要求适配(Android 10+)

Android 10+规定WiFi扫描必须在应用前台执行,后台扫描频率被严格限制。同时需确保WiFi处于开启状态。

修复:

优化WifiReceiver的Scan方法,增加WiFi状态检查:

public IEnumerable<string> Scan()
{
    tmr = new Timer(Timeout, null, TIMEOUT_MILLIS, System.Threading.Timeout.Infinite);
    // 检查并开启WiFi
    if (!wifi.IsWifiEnabled)
    {
        wifi.SetWifiEnabled(true);
        Thread.Sleep(1000); // 等待WiFi启动
    }
    // 启动扫描并校验结果
    bool scanStarted = wifi.StartScan();
    if (!scanStarted)
    {
        receiverARE.Set();
        return new List<string>();
    }
    receiverARE.WaitOne();
    return wifiNetworks;
}

4. 扫描结果有效性校验

在OnReceive方法中,需确认扫描结果是否可用,避免空数据:

public override void OnReceive(Context context, Intent intent)
{
    bool scanResultAvailable = intent.GetBooleanExtra(WifiManager.ExtraScanResultAvailable, false);
    if (!scanResultAvailable)
    {
        receiverARE.Set();
        return;
    }
    
    IList<ScanResult> scanwifinetworks = wifi.ScanResults;
    foreach (ScanResult wifinetwork in scanwifinetworks)
    {
        // 过滤空SSID
        if (!string.IsNullOrEmpty(wifinetwork.Ssid))
        {
            wifiNetworks.Add(wifinetwork.Ssid);
        }
    }
    receiverARE.Set();
}

额外注意事项

  • 确认树莓派的WiFi硬件正常,可通过系统设置验证能搜索到WiFi网络
  • Android 10+会限制扫描频率,避免短时间内多次触发扫描
  • 若需后台扫描,需额外申请ACCESS_BACKGROUND_LOCATION权限并启动前台服务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:45:27