024.MAUI 安卓—扫描附近的WiFi网络

024.MAUI 安卓—扫描附近的WiFi网络
WiFi扫描通常需要原生代码。在Android上我们需要使用原生WifiManager来扫描WiFi。注意需要相应的权限如ACCESS_FINE_LOCATION和运行时权限请求。由于实现完整功能代码量较大这里只给出框架代码。实际开发中还需要考虑Android版本差异、权限请求等。在Maui项目中我们可以通过依赖注入获取该服务然后调用扫描方法。但是请注意从Android 10API级别29开始对WiFi扫描的限制更加严格应用需要具有精确位置权限并且设备需要启用位置服务。一. 创建共享wifi扫描接口首先创建一个共享接口类namespace MauiWifi { public interface IWifiScanner { TaskListWifiNetwork ScanNetworksAsync();//扫描wifi Taskbool RequestPermissionsAsync();//请求权限 } }类中定义了一个扫描方法和一个请求权限方法方法需要用异步 task之类二.新建一个wifi 网络模型类WifiNetwork.cs每一个附近的wifi网络都会被封装成一个模型类对象public class WifiNetwork { public string Ssid { get; set; }//wifi网络名 public string Bssid { get; set; } public int SignalStrength { get; set; } // dBm public int Frequency { get; set; } // MHz public bool IsSecured { get; set; } //是否设置了密码 }三.Android 实现添加权限Android/AndroidManifest.xmluses-permission android:nameandroid.permission.ACCESS_WIFI_STATE / uses-permission android:nameandroid.permission.CHANGE_WIFI_STATE / uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_COARSE_LOCATION /这是必须是权限对于安卓10.0以上的版本还需要动态申请权限以及定位权限四。实现接口类// Platforms/Android/WifiScanner.cs 需建立在Android路径下using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; // 需要添加这个用于Task using System.Linq; // 需要添加这个用于LINQ操作 using Android.Content; using Android.Net.Wifi; using Android.OS; using Application Android.App.Application; namespace MauiWifi.Platforms.Android { // WiFi扫描器实现类实现IWifiScanner接口 public class WifiScanner : IWifiScanner { private readonly WifiManager _wifiManager; //原生wifi管理类WifiManager对象 // 构造函数初始化WifiManager public WifiScanner() { // 从Android应用上下文中获取WifiService系统服务 _wifiManager (WifiManager)Application.Context .GetSystemService(Context.WifiService); } // 请求必要的权限特别是位置权限因为Android 6.0需要位置权限来扫描WiFi public async Taskbool RequestPermissionsAsync() { // 检查Android版本是否为6.0API 23或更高 if (Build.VERSION.SdkInt BuildVersionCodes.M) { // 请求运行时位置权限 var status await Permissions.RequestAsyncPermissions.LocationWhenInUse(); // 返回权限是否被授予 return status PermissionStatus.Granted; } // Android 6.0以下版本不需要运行时权限 return true; } // 扫描附近的WiFi网络 public async TaskListWifiNetwork ScanNetworksAsync() { // 创建存储WiFi网络结果的列表 var networks new ListWifiNetwork(); // 请求权限如果权限被拒绝则返回空列表 if (!await RequestPermissionsAsync()) return networks; // 检查WiFi是否启用如果未启用则启用它 if (!_wifiManager.IsWifiEnabled) _wifiManager.SetWifiEnabled(true); // 开始扫描附近的WiFi网络 _wifiManager.StartScan(); // 等待扫描完成2秒延迟给扫描操作足够的时间 await Task.Delay(2000); // 获取扫描结果 var scanResults _wifiManager.ScanResults; // 遍历所有扫描到的WiFi网络 foreach (var result in scanResults) { // 将每个WiFi网络信息添加到列表中 networks.Add(new WifiNetwork { Ssid result.Ssid, // 网络名称 Bssid result.Bssid, // MAC地址 SignalStrength result.Level, // 信号强度dBm Frequency result.Frequency, // 频率MHz // 检查网络是否加密通过检查能力字段是否包含安全协议 IsSecured !string.IsNullOrEmpty(result.Capabilities) result.Capabilities.Contains(WEP) || result.Capabilities.Contains(PSK) || result.Capabilities.Contains(EAP) }); } // 对结果进行分组、去重和排序 // 1. 按SSID分组处理多个AP有相同SSID的情况 // 2. 从每组中选择信号最强的网络 // 3. 转换为列表返回 return networks .GroupBy(n n.Ssid) .Select(g g.OrderByDescending(n n.SignalStrength).First()) .ToList(); } } }五.在 MauiProgram.cs 中注册服务//依赖注入wifi接口IWifiScanner实现这个接口依赖Platforms.Android.WifiScanner #if ANDROID builder.Services.AddSingletonIWifiScanner, Platforms.Android.WifiScanner(); #endif完整代码如下using Microsoft.Extensions.Logging; namespace MauiWifi { public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder MauiApp.CreateBuilder(); builder .UseMauiAppApp() .ConfigureFonts(fonts { fonts.AddFont(OpenSans-Regular.ttf, OpenSansRegular); fonts.AddFont(OpenSans-Semibold.ttf, OpenSansSemibold); }); #if ANDROID builder.Services.AddSingletonIWifiScanner, Platforms.Android.WifiScanner(); #endif #if DEBUG builder.Logging.AddDebug(); #endif return builder.Build(); } } }六.在页面中使用using System.Collections.ObjectModel; namespace MauiWifi { public partial class MainPage : ContentPage { private readonly IWifiScanner _wifiScanner;//wifi扫描接口对象 //自动刷新的listwifi模型字段 _networks private ObservableCollectionWifiNetwork _networks new(); public MainPage(IWifiScanner wifiScanner) { InitializeComponent(); _wifiScanner wifiScanner;//依赖注入 wifiListView.ItemsSource _networks;//绑定到界面的 Items } //扫描按键 private async void OnScanClicked(object sender, EventArgs e) { try { var networks await _wifiScanner.ScanNetworksAsync(); _networks.Clear();//清空 foreach (var network in networks.OrderByDescending(n n.SignalStrength)) { _networks.Add(network);//逐个添加扫描到的附近WiFi } } catch (Exception ex) { await DisplayAlert(错误, ex.Message, 确定); } } } }七.XLML 页面?xml version1.0 encodingutf-8 ? ContentPage xmlnshttp://schemas.microsoft.com/dotnet/2021/maui xmlns:xhttp://schemas.microsoft.com/winfx/2009/xaml x:ClassMauiWifi.MainPage VerticalStackLayout Button Text扫描WiFi ClickedOnScanClicked Margin20/ ListView x:NamewifiListView ListView.ItemTemplate DataTemplate ViewCell VerticalStackLayout Padding10 Label Text{Binding Ssid} FontSize16 FontAttributesBold/ Label Text{Binding SignalStrength, StringFormat信号强度: {0} dBm} FontSize12/ Label Text{Binding Bssid} FontSize10 TextColorGray/ /VerticalStackLayout /ViewCell /DataTemplate /ListView.ItemTemplate /ListView /VerticalStackLayout /ContentPage运行测试原生api需在真机上运行