Flutter应用如何同时使用Wifi与移动网络满足多业务需求
实现方案
这个需求的核心是把指定请求绑定到对应的网络接口上,手机默认连接无互联网的WiFi时,会自动把所有流量切到蜂窝网络,或者反过来切到WiFi导致蜂窝不可用,所以需要主动给不同业务的请求指定网络出口。
前置说明
两大移动端系统都默认不允许双网同时承载流量,需要主动调用系统开放的多网络API实现,且需要申请对应权限:
- Android需要
ACCESS_NETWORK_STATE、CHANGE_NETWORK_STATE、ACCESS_FINE_LOCATION(Android 12+连接WiFi需要)权限 - iOS需要
NSLocalNetworkUsageDescription权限(访问本地WiFi设备)、开启Hotspot Configuration、Network Extensions能力
分端实现思路
1. 原生层网络绑定逻辑
Android端
用Android 5.0以上开放的ConnectivityManager多网络API实现:
- 先分别请求两个网络的实例:
- 蜂窝网络:指定
NetworkCapabilities.TRANSPORT_CELLULAR和NET_CAPABILITY_INTERNET过滤条件 - 外接设备WiFi:指定
NetworkCapabilities.TRANSPORT_WIFI,额外过滤要连接的设备WiFi SSID
- 蜂窝网络:指定
- 拿到两个Network对象之后,通过
network.bindSocket()把对应业务的socket绑定到指定网络,或者给HTTP请求客户端设置network.getSocketFactory()、network.getProxy()
iOS端
用iOS 12+开放的NWPathMonitor和NWConnection相关API实现:
- 分别创建两个
NWPathMonitor实例,分别监控cellular和wifi接口的路径状态 - 对于外接设备的流请求,创建
NWConnection时指定requiredInterfaceType为.wifi - 对于Google Maps的请求,指定网络接口为
.cellular,也可以直接用系统默认的有互联网能力的接口
2. Flutter层适配
方法通道封装
把原生层拿到的两个网络的请求能力封装成Flutter可调用的方法:
- 封装
bindSocketToWifi(String host, int port)方法,返回绑定到WiFi接口的socket流,用来接收外接设备的数据流 - 封装
getCellularHttpClient()方法,返回绑定到蜂窝网络的HTTP客户端实例,给Google Maps相关请求用
第三方库适配
如果你用Dio之类的网络库,可以给不同业务的Dio实例设置对应的HttpClient:
// 谷歌地图业务用的Dio实例,走蜂窝网络 final mapDio = Dio(); mapDio.httpClientAdapter = IOHttpClientAdapter( createHttpClient: () { // 调用原生方法拿到绑定了蜂窝网络的HttpClient return getCellularHttpClientFromNative(); } ); // 外接设备业务用的流,走WiFi final deviceStream = await methodChannel.invokeMethod('getDeviceStream', {'ssid':'你的设备WiFi名称'}); deviceStream.listen((data) { // 处理设备返回的流数据 });
3. 特殊场景处理
- 如果外接设备的WiFi没有互联网能力,Android默认会弹出“是否保持连接”的弹窗,你可以在原生层调用
ConnectivityManager.requestNetwork()的时候指定需要的网络,主动跳过弹窗保持WiFi连接 - Google Maps SDK如果不走自定义的HTTP客户端,你可以在原生层给整个APP的蜂窝网络做默认路由,或者用VPN模式把地图相关的域名路由到蜂窝接口,不过成本比较高,更推荐用谷歌地图的自定义瓦片加载能力,用绑定了蜂窝的HTTP客户端去加载瓦片
内容的提问来源于stack exchange,提问作者mehmet akif sayrım
相关产品推荐
相关产品推荐

