求适用于Flutter Windows与Mac平台的WiFi网络扫描插件
在Flutter Windows & Mac中实现WiFi扫描功能
Windows平台实现方案
- 使用
win32插件调用Windows原生WLAN API:- 添加依赖到
pubspec.yaml:dependencies: win32: ^5.0.0 - 核心逻辑:通过
WlanOpenHandle初始化会话,WlanEnumInterfaces获取无线网卡,再调用WlanGetAvailableNetworkList扫描并提取WiFi列表。 - 关键代码示例:
import 'package:win32/win32.dart'; Future<List<String>> scanWindowsWiFi() async { final List<String> networks = []; final hClient = calloc<HANDLE>(); final dwNegotiatedVersion = calloc<DWORD>(); final pReserved = nullptr; // 打开WLAN会话 if (WlanOpenHandle(2, pReserved, dwNegotiatedVersion, hClient) != ERROR_SUCCESS) { calloc.free(hClient); calloc.free(dwNegotiatedVersion); return networks; } // 获取网卡列表 final pIfList = calloc<Pointer<WLAN_INTERFACE_INFO_LIST>>(); if (WlanEnumInterfaces(hClient.value, pReserved, pIfList) == ERROR_SUCCESS) { final ifList = pIfList.value.ref; for (var i = 0; i < ifList.dwNumberOfItems; i++) { final ifInfo = ifList.InterfaceInfo[i]; // 获取可用网络列表 final pNetworkList = calloc<Pointer<WLAN_AVAILABLE_NETWORK_LIST>>(); if (WlanGetAvailableNetworkList( hClient.value, &ifInfo.InterfaceGuid, 0, pReserved, pNetworkList ) == ERROR_SUCCESS) { final networkList = pNetworkList.value.ref; for (var j = 0; j < networkList.dwNumberOfItems; j++) { final network = networkList.Network[j]; final ssid = String.fromCharCodes( network.dot11Ssid.SSID.asTypedList(network.dot11Ssid.uSSIDLength) ); if (ssid.isNotEmpty) networks.add(ssid); } WlanFreeMemory(pNetworkList.value); } calloc.free(pNetworkList); } WlanFreeMemory(pIfList.value); } calloc.free(pIfList); WlanCloseHandle(hClient.value, pReserved); calloc.free(hClient); calloc.free(dwNegotiatedVersion); return networks.toSet().toList(); }
- 添加依赖到
Mac平台实现方案
- 调用macOS原生CoreWLAN框架,可通过
dart:ffi封装实现:- 配置权限:在
macos/Runner/Info.plist中添加位置权限声明(macOS 10.15+扫描WiFi必须申请):<key>NSLocationWhenInUseUsageDescription</key> <string>需要获取位置信息以扫描WiFi网络</string> - 核心思路:封装
CWInterface的scanForNetworksWithName:error:方法获取WiFi列表,关键代码示例:import 'dart:ffi'; import 'package:ffi/ffi.dart'; final coreWlan = DynamicLibrary.open('/System/Library/Frameworks/CoreWLAN.framework/CoreWLAN'); // 封装CWInterface创建方法 typedef CWInterfaceCreatePtr = Pointer<Void> Function(); typedef CWInterfaceCreate = Pointer<Void> Function(); final _cwInterfaceCreate = coreWlan.lookupFunction<CWInterfaceCreatePtr, CWInterfaceCreate>('CWInterfaceCreate'); // 封装扫描方法 typedef ScanForNetworksPtr = Pointer<Void> Function(Pointer<Void>, Pointer<Void>, Pointer<Pointer<Void>>); typedef ScanForNetworks = Pointer<Void> Function(Pointer<Void>, Pointer<Void>, Pointer<Pointer<Void>>); final _scanForNetworks = coreWlan.lookupFunction<ScanForNetworksPtr, ScanForNetworks>('CWInterfaceScanForNetworksWithNameError'); // 封装CWNetwork的SSID获取方法 typedef GetSSIDPtr = Pointer<Utf8> Function(Pointer<Void>); typedef GetSSID = Pointer<Utf8> Function(Pointer<Void>); final _getSSID = coreWlan.lookupFunction<GetSSIDPtr, GetSSID>('CWNetworkSSID'); Future<List<String>> scanMacWiFi() async { final List<String> networks = []; final interface = _cwInterfaceCreate(); if (interface == nullptr) return networks; final errorPtr = calloc<Pointer<Void>>(); final networksListPtr = _scanForNetworks(interface, nullptr, errorPtr); if (errorPtr.value != nullptr) { calloc.free(errorPtr); return networks; } // 遍历网络列表(此处简化,实际需处理CoreWLAN的数组结构) // 示例中假设已获取到单个CWNetwork指针,实际需循环提取 final networkPtr = /* 从列表中提取单个CWNetwork指针 */; if (networkPtr != nullptr) { final ssidUtf8 = _getSSID(networkPtr); networks.add(ssidUtf8.toDartString()); } calloc.free(errorPtr); return networks.toSet().toList(); }
- 配置权限:在
跨平台封装建议
通过条件导入封装平台专属逻辑,实现统一调用入口:
import 'scan_windows.dart' if (dart.library.macos) 'scan_mac.dart'; abstract class WiFiScanner { Future<List<String>> scanNetworks(); }
内容的提问来源于stack exchange,提问作者Lokesh
相关产品推荐
相关产品推荐

