Flutter实战:如何用network_info_plus插件一键获取当前WiFi名称(附iOS/Android权限配置全流程)

张开发
2026/6/10 0:30:13 15 分钟阅读
Flutter实战:如何用network_info_plus插件一键获取当前WiFi名称(附iOS/Android权限配置全流程)
Flutter跨平台开发实战深度解析network_info_plus插件获取WiFi信息的完整方案在智能家居设备配网、企业内网认证等场景中自动获取设备当前连接的WiFi信息能显著提升用户体验。作为Flutter开发者我们经常需要处理这类需求但跨平台的权限差异和API限制往往让实现过程充满挑战。本文将带你从原理到实践全面掌握在Flutter应用中获取WiFi信息的专业方案。1. 技术选型与核心原理在Flutter生态中network_info_plus插件是目前最成熟的网络信息获取方案。它实际上是对原生平台API的封装Android端通过WifiManager获取SSID/BSSID需要ACCESS_NETWORK_STATE和定位权限iOS端依赖NEHotspotNetworkAPI需要com.apple.developer.networking.wifi-info权限技术难点从Android 10API 29开始Google加强了隐私保护获取SSID必须配合定位权限。这是很多开发者容易忽略的关键点。插件核心方法包括FutureString? getWifiName(); // 获取SSID FutureString? getWifiBSSID(); // 获取BSSID FutureString? getWifiIP(); // 获取IPv4地址 FutureString? getWifiIPv6(); // 获取IPv6地址 FutureString? getWifiSubmask(); // 获取子网掩码2. 项目配置全流程2.1 基础环境搭建首先在pubspec.yaml中添加依赖dependencies: network_info_plus: ^6.1.3 permission_handler: ^10.4.0执行flutter pub get后需要针对不同平台进行配置。2.2 Android平台配置修改android/app/src/main/AndroidManifest.xmlmanifest !-- 基础网络权限 -- uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE / !-- Android 10 必须的定位权限 -- uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_COARSE_LOCATION / !-- 针对不同API级别的兼容处理 -- uses-permission-sdk-23 android:nameandroid.permission.ACCESS_FINE_LOCATION android:maxSdkVersion30 / /manifest2.3 iOS平台配置iOS的配置更为复杂需要多个步骤Entitlements文件配置在Runner/Runner.entitlements中添加dict keycom.apple.developer.networking.wifi-info/key true/ /dictInfo.plist权限声明添加定位权限描述keyNSLocationWhenInUseUsageDescription/key string需要获取WiFi信息用于设备配网/string keyNSLocationAlwaysAndWhenInUseUsageDescription/key string需要获取WiFi信息用于设备配网/stringXcode工程配置在Signing Capabilities中添加Access WiFi Information能力。3. 代码实现与最佳实践3.1 基础获取实现创建一个完整的WiFi信息获取组件import package:flutter/material.dart; import package:network_info_plus/network_info_plus.dart; import package:permission_handler/permission_handler.dart; class WifiInfoWidget extends StatefulWidget { const WifiInfoWidget({super.key}); override StateWifiInfoWidget createState() _WifiInfoWidgetState(); } class _WifiInfoWidgetState extends StateWifiInfoWidget { final NetworkInfo _networkInfo NetworkInfo(); MapString, String? _wifiData {}; bool _isLoading true; Futurevoid _fetchWifiInfo() async { setState(() _isLoading true); // 检查并请求定位权限 if (!await _checkLocationPermission()) { setState(() _isLoading false); return; } // 并行获取所有网络信息 final results await Future.wait([ _networkInfo.getWifiName(), _networkInfo.getWifiBSSID(), _networkInfo.getWifiIP(), _networkInfo.getWifiSubmask(), ]); setState(() { _wifiData { SSID: results[0], BSSID: results[1], IP地址: results[2], 子网掩码: results[3], }; _isLoading false; }); } Futurebool _checkLocationPermission() async { final status await Permission.location.status; if (status.isGranted) return true; final result await Permission.location.request(); return result.isGranted; } override void initState() { super.initState(); _fetchWifiInfo(); } override Widget build(BuildContext context) { return Column( children: [ if (_isLoading) const CircularProgressIndicator() else ...[ for (final entry in _wifiData.entries) ListTile( title: Text(entry.key), subtitle: Text(entry.value ?? 未获取到数据), ), ElevatedButton( onPressed: _fetchWifiInfo, child: const Text(刷新信息), ) ] ], ); } }3.2 高级功能扩展实时监听网络变化StreamMapString, String? getWifiInfoStream() async* { final networkInfo NetworkInfo(); while (true) { yield { SSID: await networkInfo.getWifiName(), IP: await networkInfo.getWifiIP(), }; await Future.delayed(const Duration(seconds: 5)); } }多平台兼容处理FutureString? getFormattedWifiName() async { final name await NetworkInfo().getWifiName(); if (name null) return null; // Android返回的SSID常带有引号 if (name.startsWith() name.endsWith()) { return name.substring(1, name.length - 1); } return name; }4. 疑难问题解决方案4.1 常见错误排查问题现象可能原因解决方案Android返回null未授予定位权限检查ACCESS_FINE_LOCATION权限iOS崩溃缺少entitlements配置确认Xcode中WiFi权限已添加模拟器无数据模拟器无真实WiFi模块使用真机测试返回Android 12限制添加ACCESS_WIFI_STATE权限4.2 性能优化建议权限缓存首次获取权限后缓存状态避免重复请求错误重试网络不稳定时实现指数退避重试机制数据本地缓存非关键数据可考虑本地存储减少请求次数FutureString? getCachedWifiName() async { const cacheKey last_wifi_name; final prefs await SharedPreferences.getInstance(); // 先从缓存读取 final cachedName prefs.getString(cacheKey); if (cachedName ! null) return cachedName; // 缓存不存在则从网络获取 final freshName await NetworkInfo().getWifiName(); if (freshName ! null) { await prefs.setString(cacheKey, freshName); } return freshName; }5. 企业级应用实践在智能家居场景中我们通常需要将WiFi信息传递给IoT设备。这里分享一个完整的配网流程实现class SmartConfigPage extends StatefulWidget { const SmartConfigPage({super.key}); override StateSmartConfigPage createState() _SmartConfigPageState(); } class _SmartConfigPageState extends StateSmartConfigPage { final _networkInfo NetworkInfo(); String? _currentSsid; String? _currentPassword; bool _isConfiguring false; Futurevoid _startSmartConfig() async { if (_currentSsid null || _currentPassword null) return; setState(() _isConfiguring true); try { // 调用设备配网SDK await IotDevice.connect( ssid: _currentSsid!, password: _currentPassword!, ); // 配网成功后跳转 if (mounted) { Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) const ConfigSuccessPage()), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(配网失败: ${e.toString()})), ); } finally { if (mounted) setState(() _isConfiguring false); } } override void initState() { super.initState(); _loadCurrentWifi(); } Futurevoid _loadCurrentWifi() async { final name await _networkInfo.getWifiName(); setState(() _currentSsid name); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(设备配网)), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( decoration: const InputDecoration(labelText: WiFi名称), controller: TextEditingController(text: _currentSsid), onChanged: (v) _currentSsid v, ), TextField( decoration: const InputDecoration(labelText: WiFi密码), obscureText: true, onChanged: (v) _currentPassword v, ), const SizedBox(height: 20), ElevatedButton( onPressed: _isConfiguring ? null : _startSmartConfig, child: _isConfiguring ? const CircularProgressIndicator() : const Text(开始配网), ), ], ), ), ); } }在实际项目中我们发现Android 12的设备需要额外处理NEARBY_WIFI_DEVICES权限而iOS 16之后对后台WiFi访问有了更严格的限制。这些平台差异需要开发者在设计架构时就充分考虑。

更多文章