欢迎加入 CPF-Flutter 鸿蒙社区: CPF-Flutter - 开源代码托管,代码协作 - AtomGit

很多 App 在弱网时体验很差:用户点了一键换网络、连上公司 Wi-Fi、或视频加载失败,页面却不知道该提示还是该重试。要在鸿蒙应用里实时知道当前是 Wi-Fi 还是有线还是蜂窝,可以接一个现成的网络连接状态库。

这次选了 connectivity_plus,做一个叫 NetPulse 的小 Demo。功能很简单:进页面先查一次当前网络类型,之后网络一变,页面就自动跟着变;右上角还有个“刷新状态”按钮,随时手动再查一次。开始阅读、断网重连、档案下载这类“网络一变就要反应”的场景都可以照这个方式接。

NetPulse 的完整源码已经放到 atomgit,文章里的检测面板和测试代码都在这里:

项目仓库:netpulse - AtomGit

网络检测功能用的是 AtomGit 上 CPF-Flutter 维护的鸿蒙版本(flutter_plus_plugins 聚合仓库里的 connectivity_plus 包),仓库链接统一放在文末。接入代码不多,这次花时间核对的主要是依赖:connectivity_plus 的鸿蒙实现放在聚合仓库里,主包和平台接口包要指到同一个提交。下面把实际跑通的配置和过程记下来。

环境和设备

还没搭好 Flutter 鸿蒙环境的话,可以先看《Flutter OHOS 开发环境搭建指南》,链接见文末。

我这边用的环境如下,测试日期见文末。

项目版本
Flutter3.35.8-ohos-1.0.3,channel [user-branch]
Dart3.9.2
DevEco Studio26.0.0(本机 E:\DevEco Studio
编译 SDKOpenHarmony SDK 26.0.0E:\OpenHarmonySDK
验证方式Pura 90 Pro 7.0.0(26.0.0)

Windows 提示:Flutter 工程引入含原生插件的库后,构建需要符号链接能力。若构建报 symlink 相关错误,请在系统设置中开启「开发者模式」再重试(详见下文 FAQ)。

先把依赖选对

这次用的是 connectivity_plus 6.1.0,固定到提交 4ca461ac6e42c2b6e856897a8612041bef2a5a8e。它在 flutter_plus_plugins 聚合仓库里的路径是 packages/connectivity_plus/connectivity_plus。下面的配置可以直接放进应用的 pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  connectivity_plus:
    git:
      url: https://atomgit.com/CPF-Flutter/flutter_plus_plugins.git
      ref: 4ca461ac6e42c2b6e856897a8612041bef2a5a8e
      path: packages/connectivity_plus/connectivity_plus

dependency_overrides:
  connectivity_plus_platform_interface:
    git:
      url: https://atomgit.com/CPF-Flutter/flutter_plus_plugins.git
      ref: 4ca461ac6e42c2b6e856897a8612041bef2a5a8e
      path: packages/connectivity_plus/connectivity_plus_platform_interface

执行:

flutter pub get

connectivity_plus 在两个地方容易配错。

一处是 path。仓库是包含一大堆 *_plus 插件的聚合仓库,不能只写仓库地址,connectivity_plus 要落到 packages/connectivity_plus/connectivity_plus 这个子目录。

另一处是 dependency_overrides。一开始只加主包,Pub 会去 pub.dev 拉平台接口包。对鸿蒙来说,主包和平台接口包最好指向同一个 AtomGit 提交,两边消息格式才配套。我这次把两者都指到 4ca461…flutter pub get 后能在 pubspec.lock 里看到主包 6.1.0、平台接口 2.0.1 都来自同一个提交。以后升级依赖时,这两个包要一起检查。

接口就两个,够用了

connectivity_plus 的功能非常集中:查一次当前网络订阅网络变化流。整个库对外主要就 Connectivity 这一个类。

鸿蒙端底层调用的是网络能力接口,先拿默认网络,再读它的承载类型:

const netHandle = await connection.getDefaultNet();
if (netHandle.netId == 0) {
  // 无网络
} else {
  const caps = await connection.getNetCapabilities(netHandle);
  // caps.bearerTypes 里看是 BEARER_WIFI / BEARER_ETHERNET / BEARER_CELLULAR
}

原生侧还会按变化把结果通过事件通道 dev.fluttercommunity.plus/connectivity_status 推给 Dart。

Dart 端先导入:

import 'package:connectivity_plus/connectivity_plus.dart';

接口一:主动查询当前网络,调用 checkConnectivity()

final Connectivity _connectivity = Connectivity();
final List<ConnectivityResult> results = await _connectivity.checkConnectivity();

它返回一个 Future<List<ConnectivityResult>>。注意返回的是列表:一个设备可能同时有几种候选网络(比如开 Wi-Fi 又开了热点权限时)。数组包容不下时,列表里只会保留一种,且永远不为空;完全没有网络时,列表里只有一个 ConnectivityResult.none

接口二:订阅网络变化流,读取 onConnectivityChanged

StreamSubscription<List<ConnectivityResult>>? sub;
sub = _connectivity.onConnectivityChanged.listen((List<ConnectivityResult> results) {
  // 网络一变就到这里
});
// 页面销毁时记得取消
sub?.cancel();

它是异步流,网络从 Wi-Fi 切到流量、断开、重连都会推一次。流自带去重,网络没变化不会重复收到。

配这个计划用的 ConnectivityResult 有 7 种取值:

枚举含义
ConnectivityResult.wifi连接 Wi-Fi
ConnectivityResult.mobile蜂窝移动网络
ConnectivityResult.ethernet有线网络
ConnectivityResult.bluetooth蓝牙网络
ConnectivityResult.vpn正在走 VPN
ConnectivityResult.other未知类型
ConnectivityResult.none无网络(只在完全不联网时出现)

提示: checkConnectivity() 只反映“有没有可用的网络”,不保证能真实上网(比如连了需登录的公共 Wi-Fi)。要做“能不能上网”的判断,仍需自己发请求做兜底。

接到检测面板上

NetPulse 以检测面板为主页:顶部一张状态卡片,显示“已连接/未连接”和当前连接类型;下方一个“刷新状态”按钮,再往下把 7 种连接类型和“当前是否命中”列成清单。

进页面先主动查一次,同时订上变化流,网络一变页面就自动刷:

@override
void initState() {
  super.initState();
  _refresh(); // 接口一:进页面先查一次
  // 接口二:订阅变化流,网络一变自动刷新
  _subscription = _connectivity.onConnectivityChanged.listen((results) {
    if (!mounted) return;
    setState(() => _results = results);
  });
}
​
Future<void> _refresh() async {
  setState(() => _checking = true);
  try {
    final results = await _connectivity.checkConnectivity();
    if (!mounted) return;
    setState(() { _results = results; _checking = false; });
  } catch (_) {
    if (!mounted) return;
    setState(() { _results = const [ConnectivityResult.none]; _checking = false; });
  }
}
​
@override
void dispose() {
  _subscription?.cancel();
  super.dispose();
}

这是连上 Wi-Fi 后的样子。状态卡是绿色“已连接”,下方清单里 Wi-Fi 打勾:

这是没有网络的页面。状态卡变成橙色“未连接”:

关键文件:lib/main.dart 是页面和状态逻辑,按钮、卡片、清单都在这里。如果把它搬进多页面应用,建议用 RouteAware 处理阅读页/详情页被覆盖的场景,避免后台页面还占着流订阅。

下载源码,签名后装到手机

可以直接把 NetPulse 拉下来运行,依赖已经写进工程:

git clone https://atomgit.com/<你的账号>/netpulse.git
cd netpulse
flutter pub get

然后在 DevEco Studio 里完成调试签名:

  1. 用 DevEco Studio 打开 ohos 目录。

  2. 进入 File → Project Structure → Signing Configs

  3. 勾选 Automatically generate signature,给当前工程和设备生成签名,点 Apply/OK

签名完成后构建、安装:

flutter build hap --release
hdc list targets
hdc -t <设备ID> install -r build/ohos/hap/entry-default-signed.hap
hdc -t <设备ID> shell aa start -a EntryAbility -b <你的包名>

平时调页面需要热重载,可用 flutter run -d <设备ID>。若构建停在签名环节或报你本机没有签名配置,先按上面第 3 步自动生成签名即可。

手机上实际试了什么

本机静态检查与测试结果:

  • flutter analyze:通过,无问题。

  • flutter test:冒烟测试通过(注入假网络实现验证页面能渲染“Wi-Fi”“刷新状态”)。

真机上逐项操作后的结果如下:

操作结果
开机连 Wi-Fi,进页面状态卡“已连接”,列表勾选 Wi-Fi
关掉 Wi-Fi 改用蜂窝列表自动变成勾选“蜂窝移动网络”,无需点按钮
关闭所有网络状态卡“未连接”,列表勾选 0 项,类型为 none
点击“刷新状态”重新 checkConnectivity(),与当前实际一致
断网后重连流自动推送,页面由“未连接”切回对应类型

FAQ:接入时遇到的问题

找不到包,或提示 Dart SDK 版本不兼容

先看拉的是哪个分支/提交,再核对 pathconnectivity_plus 在聚合仓库里,pubspec.yaml 一定不要只写仓库 url,要带上 path: packages/connectivity_plus/connectivity_plus。本文用的 4ca461… 对应 Dart >=3.2.0、Flutter >=3.7.0,你本机 Flutter 若是 3.35 分支可直接用。

平台接口报消息格式/解码不匹配

先检查 pubspec.lockconnectivity_plus_platform_interface 的来源。如果主包来自鸿蒙仓库、平台接口却来自 pub.dev,两端可能对不上。本文用 dependency_overrides 把平台接口也指到同一个提交解决。改完重新 flutter pub get,再重建、安装 HAP;涉及原生依赖的变化,不能只做热重载。

构建报 symlink 相关错误(Windows)

flutter pub get 解析成功了,但构建时提示“Building with plugins requires symlink support”。Flutter 在 Windows 上引入含原生插件的库需要符号链接能力。到系统设置搜索「开发者模式」并打开(或运行 start ms-settings:developers),重启终端后再构建即可。

checkConnectivity 返回了值,但页面还是提示连不上

connectivity_plus 只报告“有没有可用网络”,不保证能真正上网。遇到需认证的公共 Wi-Fi,会显示 wifi 但实际不通。需要“能否上网”的判断时,应另发一次网络请求做兜底,不要只信连接类型。

需要申请网络权限吗?

鸿蒙端检测只用 @ohos.net.connection,读取网络连接状态不需要运行时权限申请。工程模板里的 ohos.permission.INTERNET 是 Flutter 调试用的,和网络检测不是一回事。

发现库的问题,怎么反馈

1. 提交 Issue,说明问题和复现步骤

从文末链接进入 connectivity_plus 鸿蒙版本仓库,打开 Issues 页面,先搜索有没有相同的问题。如果没有,点击右上角的 新建 Issue,填写问题标题和复现信息。

报告时把“只引入主包”的配置贴出来,再附上 pubspec.lock 中实际解析的平台接口版本,说明预期什么、实际报什么错,以及 Flutter 版本、设备系统、提交号和关键日志。

2. Fork 项目,在自己的仓库中修改

如果问题能自己修,点击上游仓库右上角的 Fork。在 Fork 页面确认项目名称、自己的账号和要复制的分支,再点击 创建 Fork 项目

Fork 完成后,把自己的仓库克隆到本地,并添加上游仓库。下面以补充依赖说明为例,<你的账号> 换成自己的 AtomGit 账号:

git clone https://atomgit.com/<你的账号>/flutter_plus_plugins.git
cd flutter_plus_plugins
git remote add upstream https://atomgit.com/CPF-Flutter/flutter_plus_plugins.git
git fetch upstream
git switch -c docs/ohos-connectivity-pairing upstream/br_connectivity_plus-v6.1.0_ohos

改好中文 README,把依赖配对写清楚,检查差异后推到自己的 Fork:

git diff --check
git add [想提交的文件]
git commit -m "docs: clarify OHOS connectivity dependency pairing"
git push -u origin docs/ohos-connectivity-pairing
3. 创建 PR,把修改提交给上游

推送后回到自己的 AtomGit Fork 仓库,点击 同步源项目,选择包含修改的分支。有超前提交时,可以通过弹窗中的 创建并提交 PR 进入 PR 创建页面。

在 PR 页面核对源仓库和源分支,目标仓库选 CPF-Flutter/flutter_plus_plugins 上游,目标分支按维护者当前要求选择。填写标题和说明,写清原来哪里配不对、改了什么、用哪个版本验证过;有对应 Issue 就关联上,确认差异后提交 PR。

相关链接

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐