Flutter Network Info Plus 鸿蒙适配要点总结
概述
Network Info Plus 是一个流行的 Flutter 插件,用于获取设备的网络信息,包括 Wi-Fi 名称、BSSID、IP 地址等。本文将详细介绍该插件在鸿蒙(HarmonyOS)平台的适配实现,包括功能介绍、技术实现和注意事项。
创建ohos模块
flutter create . --org dev.fluttercommunity.plus --template=plugin --platforms=ohos
功能介绍
支持的网络信息获取功能
- Wi-Fi 名称 (SSID) - 获取当前连接的 Wi-Fi 网络名称
- Wi-Fi BSSID - 获取 Wi-Fi 基站的 MAC 地址
- IPv4 地址 - 获取设备的 IPv4 地址
- IPv6 地址 - 获取设备的 IPv6 地址
- 子网掩码 - 获取网络的子网掩码
- 网关 IP - 获取网络网关地址
- 广播 IP - 获取网络广播地址
API 接口
class NetworkInfo {
Future<String?> getWifiName(); // 获取 Wi-Fi 名称
Future<String?> getWifiBSSID(); // 获取 Wi-Fi BSSID
Future<String?> getWifiIP(); // 获取 IPv4 地址
Future<String?> getWifiIPv6(); // 获取 IPv6 地址
Future<String?> getWifiSubmask(); // 获取子网掩码
Future<String?> getWifiGatewayIP(); // 获取网关 IP
Future<String?> getWifiBroadcast(); // 获取广播 IP
}
鸿蒙平台技术实现
1. 插件架构
鸿蒙端实现采用标准的 Flutter 插件架构:
export default class NetworkInfoPlusOhosPlugin implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(),
"dev.fluttercommunity.plus/network_info");
this.channel.setMethodCallHandler(this);
}
}
2. 核心 API 使用
Wi-Fi 信息获取
使用鸿蒙的 @kit.ConnectivityKit
中的 wifiManager
:
import { wifiManager } from '@kit.ConnectivityKit';
// 获取 Wi-Fi 名称
async getWifiName() {
let wifiMessage = await wifiManager.getLinkedInfo().then(data => {
return data.ssid;
}).catch((error: number) => {
console.info("get linked info error");
});
return wifiMessage;
}
// 获取 BSSID
async getWifiBSSID() {
let wifiMessage = await wifiManager.getLinkedInfo().then(data => {
if (data && data.bssid !== undefined && data.bssid !== null) {
return data.bssid;
}
return null;
});
return wifiMessage;
}
IP 地址信息获取
// 获取 IPv4 地址
getWifiIPAddress() {
const bytes = [
wifiManager.getIpInfo().ipAddress >>> 24,
(wifiManager.getIpInfo().ipAddress >>> 16) & 0xFF,
(wifiManager.getIpInfo().ipAddress >>> 8) & 0xFF,
wifiManager.getIpInfo().ipAddress & 0xFF
];
return bytes.map(byte => byte.toString()).join('.');
}
// 获取 IPv6 地址
getIpV6() {
let info = wifiManager.getIpv6Info().linkIpv6Address;
return info === '' ? null : info;
}
网络计算功能
// IP 地址与整数转换
ipToInt(ip: string): number {
let parts = ip.split('.');
let num = 0;
for (let i = 0; i < parts.length; i++) {
num |= parseInt(parts[i], 10) << (24 - 8 * i);
}
return num;
}
// 计算广播地址
getBroadcastIP() {
const ipInt = this.ipToInt(this.getWifiIPAddress() as string);
const subnetMaskInt = this.ipToInt(this.getWifiSubnetMask() as string);
const broadcastInt = (ipInt & subnetMaskInt) | (~subnetMaskInt);
return this.intToIp(broadcastInt);
}
3. 方法调用处理
onMethodCall(call: MethodCall, result: MethodResult): void {
switch (call.method) {
case "wifiName":
this.getWifiName().then(data => {
result.success(data || null);
});
break;
case "wifiBSSID":
this.getWifiBSSID().then(data => {
// 失败时返回默认 MAC 地址
result.success(data || '02:00:00:00:00:00');
});
break;
// ... 其他方法
}
}
Flutter 端使用示例
基本使用
class _MyHomePageState extends State<MyHomePage> {
final NetworkInfo _networkInfo = NetworkInfo();
String _connectionStatus = 'Unknown';
Future<void> _initNetworkInfo() async {
String? wifiName, wifiBSSID, wifiIPv4;
try {
// 鸿蒙平台特殊处理
if (Platform.operatingSystem == 'ohos') {
wifiName = await _networkInfo.getWifiName();
wifiBSSID = await _networkInfo.getWifiBSSID();
}
wifiIPv4 = await _networkInfo.getWifiIP();
setState(() {
_connectionStatus = 'Wifi Name: $wifiName\n'
'Wifi BSSID: $wifiBSSID\n'
'Wifi IPv4: $wifiIPv4\n';
});
} catch (e) {
print('获取网络信息失败: $e');
}
}
}
权限处理
// 权限请求(主要针对 Android/iOS)
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.operatingSystem == 'ohos')) {
final permissionStatus = await Permission.locationWhenInUse.request();
if (permissionStatus.isGranted) {
wifiBSSID = await _networkInfo.getWifiBSSID();
} else {
// 鸿蒙平台权限被拒绝时的特殊处理
if (Platform.operatingSystem == 'ohos') {
try {
wifiBSSID = await _networkInfo.getWifiBSSID();
} catch (e) {
wifiBSSID = 'Unauthorized to get Wifi BSSID';
}
}
}
}
权限配置
鸿蒙权限要求
在 module.json5
中添加必要权限:
{
"requestPermissions": [
{
"name": "ohos.permission.GET_WIFI_INFO",
"reason": "$string:wifi_info_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.GET_NETWORK_INFO",
"reason": "$string:network_info_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
权限说明文件
在 string.json
中添加权限说明:
{
"string": [
{
"name": "wifi_info_reason",
"value": "获取WiFi信息用于网络状态显示"
},
{
"name": "network_info_reason",
"value": "获取网络信息用于连接状态检测"
},
{
"name": "internet_reason",
"value": "访问网络用于数据传输"
}
]
}
注意事项
1. 平台差异
- 权限模型:鸿蒙的权限模型与 Android/iOS 有所不同,需要在
module.json5
中声明 - API 差异:鸿蒙使用
wifiManager
而非 Android 的WifiManager
- 返回值处理:某些情况下鸿蒙 API 返回的数据格式可能与其他平台不同
2. 错误处理
// 建议的错误处理模式
try {
let result = await wifiManager.getLinkedInfo();
return result.ssid || null;
} catch (error) {
console.error("获取WiFi信息失败:", error);
return null;
}
3. 调试建议
- 使用详细的日志输出来跟踪问题
- 检查设备的 Wi-Fi 连接状态
- 验证权限是否正确配置
- 测试不同的网络环境
4. 性能考虑
- 避免频繁调用网络信息 API
- 考虑缓存机制减少重复请求
- 异步处理避免阻塞 UI 线程
5. 兼容性
- 确保在不同鸿蒙版本上的兼容性
- 处理 API 不可用的情况
- 提供合理的默认值和错误信息
最佳实践
1. 统一的错误处理
Future<String?> _safeGetNetworkInfo(Future<String?> Function() getter, String errorMsg) async {
try {
return await getter();
} on PlatformException catch (e) {
developer.log(errorMsg, error: e);
return 'Failed to get network info';
}
}
2. 平台特定逻辑
if (Platform.operatingSystem == 'ohos') {
// 鸿蒙特定处理逻辑
} else if (Platform.isAndroid) {
// Android 特定处理逻辑
}
3. 权限检查
Future<bool> _checkPermissions() async {
if (Platform.operatingSystem == 'ohos') {
// 鸿蒙权限检查逻辑
return true; // 简化示例
}
return await Permission.locationWhenInUse.isGranted;
}
总结
Network Info Plus 的鸿蒙适配展示了如何将 Flutter 插件扩展到新平台的完整流程。通过合理的架构设计、详细的错误处理和平台特定的优化,可以为鸿蒙用户提供与其他平台一致的网络信息获取体验。
在实际开发中,建议:
- 充分测试各种网络环境
- 处理好权限和异常情况
- 保持与其他平台的 API 一致性
- 关注鸿蒙系统的更新和 API 变化
这种跨平台适配的经验也可以应用到其他 Flutter 插件的鸿蒙适配工作中。