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

求适用于Flutter Windows与Mac平台的WiFi网络扫描插件

在Flutter Windows & Mac中实现WiFi扫描功能

Windows平台实现方案

  • 使用win32插件调用Windows原生WLAN API:
    1. 添加依赖到pubspec.yaml:
      dependencies:
        win32: ^5.0.0
      
    2. 核心逻辑:通过WlanOpenHandle初始化会话,WlanEnumInterfaces获取无线网卡,再调用WlanGetAvailableNetworkList扫描并提取WiFi列表。
    3. 关键代码示例:
      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();
      }
      
    注意:Windows平台需确保WLAN AutoConfig服务处于启用状态,且应用需以管理员权限运行才能完成扫描。

Mac平台实现方案

  • 调用macOS原生CoreWLAN框架,可通过dart:ffi封装实现:
    1. 配置权限:在macos/Runner/Info.plist中添加位置权限声明(macOS 10.15+扫描WiFi必须申请):
      <key>NSLocationWhenInUseUsageDescription</key>
      <string>需要获取位置信息以扫描WiFi网络</string>
      
    2. 核心思路:封装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();
      }
      
    注意:Release模式下应用需签名才能正常访问CoreWLAN框架。

跨平台封装建议

通过条件导入封装平台专属逻辑,实现统一调用入口:

import 'scan_windows.dart' if (dart.library.macos) 'scan_mac.dart';

abstract class WiFiScanner {
  Future<List<String>> scanNetworks();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:25:16