Flutter OpenHarmony 三方库适配实战:package_info_plus 应用信息
一、项目信息
| 项目 | 内容 |
|---|---|
| 仓库名称 | package_info_plus |
| 仓库地址 | https://atomgit.com/oh-flutter/package_info_plus |
| 上游版本 | package_info_plus 10.2.2 |
| OHOS TAG | 10.2.2-ohos.1 |
| 方法通道 | dev.fluttercommunity.plus/package_info |
| OHOS 入口 | PackageInfoPlugin.ets |
| 构建产物 | entry-default-unsigned.hap |
package_info_plus的价值在于提供一个跨平台的应用元信息接口。业务层只调用PackageInfo.fromPlatform(),不关心 Android 的PackageManager、iOS 的Bundle或 OHOS 的BundleInfo。适配的重点是把 OHOSBundleInfo的字段稳定地转换成上游 Dart API。
环境搭建与版本
下面是本次适配实际使用的环境。环境搭建过程这里不再展开,直接看 Flutter OH 环境搭建指南。
| 项目 | 版本/说明 |
|---|---|
| Flutter OH | 3.44.9+ohos-0.0.1-canary1 |
| Dart | 3.12.2 |
| DevEco Studio | 26.0.0 |
| HarmonyOS SDK | API 26 |
| 目标仓库 | package_info_plus |
二、原库接口与 OHOS 映射
| Dart API / 字段 | OHOS 数据来源 | 说明 |
|---|---|---|
appName | appInfo.labelId+resourceManager | 通过资源 ID 读取应用显示名称 |
packageName | bundleInfo.name | 当前应用包名 |
version | bundleInfo.versionName | 版本名称 |
buildNumber | bundleInfo.versionCode | 版本号转字符串 |
buildSignature | bundleInfo.signatureInfo.fingerprint | 系统返回的签名指纹 |
installTime | bundleInfo.installTime | 毫秒时间戳转换为DateTime |
updateTime | bundleInfo.updateTime | 毫秒时间戳转换为DateTime |
installerStore | 当前无 OHOS 对应字段 | 返回空字符串 |
OHOS 插件只实现一个方法getAll。Dart 平台接口拿到 Map 后构造PackageInfo,因此业务代码与上游 API 保持一致。
三、插件入口与生命周期
根pubspec.yaml增加 OHOS 声明:
flutter:plugin:platforms:ohos:package:dev.fluttercommunity.plus.packageinfopluginClass:PackageInfoPluginArkTS 插件在引擎挂载时创建方法通道:
constCHANNEL_NAME='dev.fluttercommunity.plus/package_info';onAttachedToEngine(binding:FlutterPluginBinding):void{this.applicationContext=binding.getApplicationContext();this.methodChannel=newMethodChannel(binding.getBinaryMessenger(),CHANNEL_NAME,);this.methodChannel.setMethodCallHandler(this);}onDetachedFromEngine(binding:FlutterPluginBinding):void{this.applicationContext=null;this.methodChannel?.setMethodCallHandler(null);this.methodChannel=null;}getAll的核心读取逻辑如下:
constbundleFlags=bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION|bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO;constbundleInfo=bundleManager.getBundleInfoForSelfSync(bundleFlags);constappInfo=bundleInfo.appInfo;infoMap.set('appName',this.applicationContext?.resourceManager.getStringSync(appInfo.labelId)??'',);infoMap.set('packageName',bundleInfo.name);infoMap.set('version',bundleInfo.versionName);infoMap.set('buildNumber',bundleInfo.versionCode.toString());infoMap.set('buildSignature',bundleInfo.signatureInfo.fingerprint??'');infoMap.set('installerStore','');infoMap.set('installTime',bundleInfo.installTime.toString());infoMap.set('updateTime',bundleInfo.updateTime.toString());result.success(infoMap);这段代码有三个容易踩坑的地方:
- 必须请求
GET_BUNDLE_INFO_WITH_SIGNATURE_INFO,否则签名指纹可能为空。 labelId需要通过应用 Context 的资源管理器读取,不能把资源 ID 直接返回给 Dart。- OHOS 时间字段是毫秒时间戳,ArkTS 返回字符串,Dart 平台接口负责转换为
DateTime。
OHOS 工程目录创建
本次适配前,上游仓库没有ohos/目录。适配分支上按 Flutter OH 的插件工程约束创建平台目录,再把 ArkTS 入口接入pubspec.yaml:
gitswitch-c<your-ohos-adaptation-branch>flutter create--platformsohos.工程生成后至少保留以下边界:
ohos/ ├── index.ets ├── oh-package.json5 └── src/main/ ├── module.json5 └── ets/components/plugin/示例工程还需要生成example/ohos/,并在插件pubspec.yaml的flutter.plugin.platforms.ohos中声明pluginClass;只创建目录、没有注册入口,Dart 方法通道仍然不会工作。
四、业务使用
import'package:flutter/material.dart';import'package:package_info_plus/package_info_plus.dart';Future<void>main()async{WidgetsFlutterBinding.ensureInitialized();finalinfo=awaitPackageInfo.fromPlatform();debugPrint('应用:${info.appName}');debugPrint('包名:${info.packageName}');debugPrint('版本:${info.version}+${info.buildNumber}');debugPrint('安装时间:${info.installTime}');debugPrint('更新时间:${info.updateTime}');runApp(constApp());}classAppextendsStatelessWidget{constApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnconstMaterialApp(home:Scaffold(body:Center(child:Text('package_info_plus'))),);}}如果业务只需要版本号,可以封装一个不暴露平台细节的仓库类:
classAppVersionRepository{Future<String>currentVersion()async{finalinfo=awaitPackageInfo.fromPlatform();return'${info.version}+${info.buildNumber}';}}这样升级 OHOS 插件时,业务层不需要修改调用方式。
五、权限与限制
读取自身应用信息不需要额外权限。插件不访问网络,也不读取其他应用。当前installerStore在 OHOS 上没有可靠对应值,因此统一返回空字符串;如果业务把它作为安装渠道统计字段,应改成服务端埋点或 OHOS 自己的渠道字段。
签名指纹只能作为辅助校验信息,不能替代服务端 token、设备证明或签名校验。应用升级、重新签名或系统迁移后,指纹可能发生变化。
适配过程 FAQ 与解决方案
为什么版本字段要从bundleInfo读取?
解决方案:OHOS 的版本号由应用配置和系统包信息服务共同维护。直接拼接包名或读取自定义配置会漏掉发行版差异,升级应用后也可能显示旧值。
versionCode在不同发行版为什么可能不同?
解决方案:它受应用打包、签名和系统分发配置影响。适配层应原样返回系统值,不要把它截断成短整数或强行改成 Flutter 的 buildNumber。
返回空值时,如何判断是插件问题还是应用配置?
解决方案:先用hdc shell bm dump或系统应用信息确认包名和版本,再检查 ArkTS 返回 map。若系统值存在但 Dart 为空,优先排查通道字段名和类型转换。
升级上游后如何确认版本一致?
解决方案:同时检查插件pubspec.yaml、OHOSoh-package.json5、示例应用配置和文章基线。只改其中一处会导致文档、HAR 和示例显示不同版本。
六、构建与测试记录
flutter pub get flutter analyze fluttertestcdexample flutter build hap--debug--no-codesign本次适配验证结果:
flutter analyze:无问题。flutter test:8 个测试全部通过。- 示例工程
flutter build hap --debug --no-codesign:成功生成entry-default-unsigned.hap。
版本与提交基线
| 项目 | 版本/地址 |
|---|---|
| 上游包 | package_info_plus |
| 上游最新版本 | 10.2.2 |
| 文章目标基线 | 10.2.2-ohos.1 |
| 当前已发布 TAG | 10.2.2-ohos.1 |
| 适配分支 | main |
| 目标最新 TAG | 10.2.2-ohos.1 |
| 最终提交 | bf71054 |
版本号更新只代表文章和适配分支的基线已对齐;涉及上游 API 变更时,仍需在该 TAG 上重新运行 Dart 测试、ArkTS 编译、HAP 安装和真机回归。
参考资料和仓库地址
- 适配仓库主页
- 适配分支 main
- 当前已发布 TAG 10.2.2-ohos.1
- 目标最新 TAG 10.2.2-ohos.1
- 最终提交 bf71054
- ArkTS 通道实现
- 鸿蒙适配说明
- pub.dev 包页面
- pub.dev 10.2.2 版本页
- 上游仓库
- Flutter 官方插件与平台通道文档
- Flutter OH 鸿蒙 SDK 仓库
欢迎加入 CPF-Flutter 鸿蒙社区。
七、目录结构
package_info_plus/ ├── lib/ │ └── package_info_plus.dart ├── ohos/ │ └── src/main/ets/dev/fluttercommunity/plus/packageinfo/ │ └── PackageInfoPlugin.ets ├── example/ ├── packages/ │ └── package_info_plus_platform_interface/ └── test/八、社区与交流
欢迎加入 Flutter OpenHarmony 适配社区,提交问题、补充真机验证或共同完善其他三方库:
- CPF-Flutter 社区
- 本仓库 Issues
- 提交 Pull Request
反馈时请附上 Flutter OHOS 版本、OpenHarmony SDK 版本、设备型号、复现步骤、日志和期望结果。