如何在Flutter中实现WiFi网络设备Mac地址列表查询?
实现Flutter中获取当前WiFi网络设备及Mac地址的方案
由于系统权限限制,多数Flutter第三方库无法直接获取局域网设备的Mac地址,下面提供原生平台集成的可行方案,通过Flutter与原生代码通信实现需求。
Android 端实现步骤
1. 配置权限
在android/app/src/main/AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- Android 12+ 额外需要 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
注:Android 10+ 无法直接获取设备自身Mac,但通过读取ARP缓存可获取局域网内其他设备的Mac地址。
2. 编写原生扫描代码
创建Java工具类读取ARP缓存:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class WifiDeviceScanner { public static List<String> getConnectedDevices() { List<String> devices = new ArrayList<>(); try { Process process = Runtime.getRuntime().exec("arp -a"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { String[] parts = line.split("\\s+"); if (parts.length >= 2) { String ip = parts[0]; String mac = parts[1]; devices.add("IP: " + ip + " | Mac: " + mac); } } reader.close(); process.waitFor(); } catch (Exception e) { e.printStackTrace(); } return devices; } }
在MainActivity中注册MethodChannel与Flutter通信:
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity: FlutterActivity() { private val CHANNEL = "com.example.wifi_scanner/device" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "getConnectedDevices") { val devices = WifiDeviceScanner.getConnectedDevices() result.success(devices) } else { result.notImplemented() } } } }
3. Flutter端调用
import 'package:flutter/services.dart'; class WifiDeviceService { static const MethodChannel _channel = MethodChannel('com.example.wifi_scanner/device'); static Future<List<String>?> getConnectedDevices() async { try { final List<dynamic> result = await _channel.invokeMethod('getConnectedDevices'); return result.cast<String>(); } on PlatformException catch (e) { print("扫描失败: ${e.message}"); return null; } } }
在UI中调用该方法,将返回的设备列表渲染即可。
iOS 端实现步骤
iOS隐私限制更严格,仅能通过arp命令尝试获取ARP缓存,且需用户授权局域网访问。
1. 配置权限
在ios/Runner/Info.plist中添加:
<key>NSLocalNetworkUsageDescription</key> <string>需要访问局域网以扫描连接设备</string> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsLocalNetworking</key> <true/> </dict>
2. 编写原生扫描代码
创建Swift工具类:
import Foundation class WifiDeviceScanner { static func getConnectedDevices() -> [String] { var devices = [String]() let task = Process() task.executableURL = URL(fileURLWithPath: "/usr/sbin/arp") task.arguments = ["-a"] let pipe = Pipe() task.standardOutput = pipe do { try task.run() let data = pipe.fileHandleForReading.readDataToEndOfFile() guard let output = String(data: data, encoding: .utf8) else { return devices } let lines = output.components(separatedBy: "\n") for line in lines { let parts = line.components(separatedBy: .whitespaces).filter { !$0.isEmpty } if parts.count >= 2 { let ip = parts[0] let mac = parts[1] devices.append("IP: \(ip) | Mac: \(mac)") } } task.waitUntilExit() } catch { print(error.localizedDescription) } return devices } }
在AppDelegate中注册MethodChannel:
import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let CHANNEL = "com.example.wifi_scanner/device" override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler { call, result in if call.method == "getConnectedDevices" { let devices = WifiDeviceScanner.getConnectedDevices() result.success(devices) } else { result.notImplemented() } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
Flutter端调用逻辑与Android完全一致。
注意事项
- Android 10+ 必须申请位置权限,否则无法读取ARP缓存;
- iOS 14+ 部分设备Mac地址可能显示为
incomplete,受系统隐私限制; - 部分路由器会隐藏设备Mac地址,导致无法获取。
内容的提问来源于stack exchange,提问作者Aldama
相关产品推荐
相关产品推荐

