同一WiFi下无需互联网的移动设备数据共享Flutter实现方案咨询
Flutter 同WiFi/LAN无公网设备数据共享(类WiFi Direct能力)实现方案
核心实现思路
- 同一现有WiFi场景:用局域网服务发现+点对点Socket通信实现,仅需基础网络权限即可运行
- 无现有WiFi场景:由一端设备主动创建WiFi热点/SoftAP,其他设备接入后走上述局域网通信逻辑,实现类WiFi Direct的直连效果
关键步骤实现
1. 前置权限配置
Android端(AndroidManifest.xml)
<!-- 基础网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 安卓12+ 附近WiFi设备权限 --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" /> <!-- 安卓12及以下版本定位权限(用于WiFi扫描) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="32" />
iOS端(Info.plist)
<key>NSLocalNetworkUsageDescription</key> <string>需要访问本地网络以实现设备间数据共享</string> <key>NSBonjourServices</key> <array> <string>_你的应用标识._tcp</string> </array>
2. 局域网服务发现
可借助nsd(网络服务发现)、multicast_dns等Pub包实现,逻辑为:服务端注册自定义服务,广播自身IP和端口;客户端扫描同局域网下的对应服务,获取连接信息。
// 服务端注册服务示例(使用nsd包) final nsd = Nsd(); final service = Service( name: '自定义服务名', type: '_你的应用标识._tcp', port: 8888, // 自定义通信端口 ); await nsd.register(service);
// 客户端扫描服务示例 await for (final Service service in nsd.discoverServices('_你的应用标识._tcp')) { if (service.name == '自定义服务名' && service.addresses?.isNotEmpty == true) { final serverHost = service.addresses!.first.address; final serverPort = service.port; // 拿到服务端地址后即可发起Socket连接 } }
3. 点对点数据传输
服务端启动ServerSocket监听指定端口,客户端连接成功后即可双向传输数据:
- 文本类数据可直接序列化后传输
- 大文件/二进制数据采用流分片传输,避免内存溢出
4. 无现有WiFi场景适配
如果没有公共WiFi网络,需要一端开启热点组网:
- Android端可通过系统API或相关工具包开启便携热点,热点开启后服务端取自身网关IP(通常为192.168.x.1网段)即可正常注册服务
- iOS受系统限制无法通过代码自动开启热点,需引导用户手动开启个人热点后再走后续连接逻辑
常见坑点
- 安卓12+无需申请定位权限,仅需
NEARBY_WIFI_DEVICES权限即可完成局域网服务扫描 - iOS首次触发本地网络访问时会弹出权限申请弹窗,用户拒绝后无法进行设备发现,需引导用户到系统设置中开启权限
- 部分定制安卓ROM对热点创建、局域网广播做了限制,需要做单独兼容适配
内容的提问来源于stack exchange,提问作者Manas Madan
相关产品推荐
相关产品推荐

