当前位置: 首页 > news >正文

Flutter到HarmonyOS Next 的跨越:memory_info库的鸿蒙适配之旅

Flutter到鸿蒙的跨越:memory_info库的鸿蒙适配之旅

本项目作者:kirk/坚果

您可以使用这个Flutter插件来更改应用程序图标上的角标

作者仓库:https://github.com/MrOlolo/memory_info/tree/master/memory_info

在数字化浪潮的推动下,跨平台开发框架如 Flutter 凭借其高效、便捷的特性,成为了开发者们的宠儿。而鸿蒙系统的崛起,更是为跨平台开发注入了新的活力。为了助力开发者在鸿蒙生态中快速实现 memory_info可帮助您获取设备内存信息(ram&rom),本文将深入浅出地为大家解析如何适配 memory_info 三方库至鸿蒙平台。

一、适配鸿蒙版 memory_info 三方库

(一)版本选择与仓库简介

我们先去 pub 上查看最新版本,我们选择以 0.0.10版本为基础进行适配。memory_info可帮助您获取设备内存信息(ram&rom),其 GitHub 仓库为https://github.com/MrOlolo/memory_info/tree/master/memory_info ,我们的目标是将这个插件适配到鸿蒙平台。

(二)引入背景与使用场景

在 OpenHarmony 北向生态的发展过程中,许多已经适配了 Flutter 的厂商在接入 OpenHarmony 时,都希望能够继续使用 memory_info 来实现内存查看功能。因此,我们提供了这个适配方案,采用插件化的适配器模式,帮助生态伙伴快速实现产品化。

本方案适用于已经支持 Flutter 框架的设备在移植到 OpenHarmony 系统过程中,作为一个备选方案。

(三)使用文档与插件库使用

适配 OpenHarmony 平台的详细使用指导可以参考:Flutter使用指导文档

在项目中使用该插件库时,只需在 pubspec.yaml 文件的 dependencies 中新增如下配置:

dependencies:
  memory_info:
    git:
      url: "https://gitcode.com/nutpi/memory_info.git"
      path: ""

然后在项目根目录运行 flutter pub get,即可完成依赖添加

接下来是具体的适配过程。

二、适配过程详解

(一)准备工作

确保已经配置好了 Flutter 开发环境,具体可参考 Flutter 配置指南。同时,从 官方插件库 下载待适配的三方插件。本指导书, 以适配 memory_info 为例

image-20250417200546042

(二)插件目录结构

下载并解压插件后,我们会看到以下目录结构:

  • lib :对接 Dart 端代码的入口,由此文件接收到参数后,通过 channel 将数据发送到原生端。
  • android :安卓端代码实现目录。
  • ios :iOS 原生端实现目录。
  • example :一个依赖于该插件的 Flutter 应用程序,用于说明如何使用它。
  • README.md :介绍包的文件。
  • CHANGELOG.md :记录每个版本中的更改。
  • LICENSE :包含软件包许可条款的文件。

(三)创建插件的鸿蒙模块

在插件目录下,打开 Terminal,执行以下命令来创建一个鸿蒙平台的 Flutter 模块:

flutter create . --org com.mrololo.memory_info --template=plugin --platforms=ohos

步骤:

  1. 用vscode/trae打开刚刚下载好的插件。

  2. 打开Terminal,cd到插件目录下。

  3. 执行命令flutter create . --org com.mrololo.memory_info --template=plugin --platforms=ohos 创建一个ohos平台的flutter模块。

第一个问题,修改sdk的版本,适配旧版本。

我们做好修改就好。

(四)在根目录下添加鸿蒙平台配置

在项目根目录的 pubspec.yaml 文件中,添加鸿蒙平台的相关配置:

name: memory_info
description: Flutter package to get device memory info(ram&rom) at android/ios devices
repository: https://com.nutpi.memory_info/
version: 0.0.4

environment:
  sdk: ">=2.12.0 <4.0.0"
  flutter: ">=1.20.0"

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec# The following section is specific to Flutter.
flutter:
  plugin:
    platforms:
      android:
        package: com.mrololo.memory_info
        pluginClass: MemoryInfoPlugin
      ios:
        pluginClass: MemoryInfoPlugin
      ohos:
        package: com.mrololo.memory_info
        pluginClass: MemoryInfoPlugin

(五)编写鸿蒙插件的原生 ArkTS模块

1. 创建鸿蒙插件模块

使用 DevEco Studio 打开鸿蒙项目。

2. 修改相关配置文件

ohos 目录内的 oh-package.json5 文件中添加 libs/flutter.har 依赖,并创建 .gitignore 文件,添加以下内容以忽略 libs 目录:

/node_modules
/oh_modules
/local.properties
/.preview
/.idea
/build
/libs
*.har
/.cxx
/.test
/BuildProfile.ets
/oh-package-lock.json5

oh-package.json5 文件内容如下:

{"name": "memory_info","version": "1.0.0","description": "Flutter package to get device memory info(ram&rom) at Android/ios/OpenHarmony devices","main": "index.ets","author": "nutpi","license": "Apache-2.0","dependencies": {"@ohos/flutter_ohos": "file:./har/flutter.har"}
}

ohos 目录下创建 index.ets 文件,导出配置:

import MemoryInfoPlugin from './src/main/ets/components/plugin/MemoryInfoPlugin';
export default MemoryInfoPlugin;
3. 编写 ETS 代码

ohos的api可以参考:https://gitcode.com/openharmony/docs

以下是 MemoryInfoPlugin 文件的代码示例:

import {FlutterPlugin,FlutterPluginBinding,MethodCall,MethodCallHandler,MethodChannel,MethodResult,
} from '@ohos/flutter_ohos';
import { storageStatistics,statfs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hidebug } from '@kit.PerformanceAnalysisKit';
import appManager from '@ohos.application.appManager';/** MemoryInfoPlugin **/
export default class MemoryInfoPlugin implements FlutterPlugin, MethodCallHandler {private channel: MethodChannel | null = null;constructor() {}getUniqueClassName(): string {return "MemoryInfoPlugin"}onAttachedToEngine(binding: FlutterPluginBinding): void {this.channel = new MethodChannel(binding.getBinaryMessenger(), "com.nutpi.memory_info");this.channel.setMethodCallHandler(this)}onDetachedFromEngine(binding: FlutterPluginBinding): void {if (this.channel != null) {this.channel.setMethodCallHandler(null)}}onMethodCall(call: MethodCall, result: MethodResult)  {if (call.method == "getPlatformVersion") {result.success("OpenHarmony ^ ^ ")} else if (call.method == "getDiskSpace") {try {const Info = new Map<string, number>();storageStatistics.getTotalSize()// 获取内置存储的总空间大小(单位为Byte),同步返回let diskTotalSpaceBytes =  storageStatistics.getFreeSizeSync();// 获取内置存储的可用空间大小(单位为Byte),同步返回let diskFreeSpaceBytes =  storageStatistics.getTotalSizeSync();// 转换为 MBconst mbFactor = 1024 * 1024;let diskTotalSpaceMB = diskTotalSpaceBytes / mbFactor;let diskFreeSpaceMB = diskFreeSpaceBytes / mbFactor;Info.set("diskTotalSpace", diskTotalSpaceMB);Info.set("diskFreeSpace", diskFreeSpaceMB);console.info(`getDiskSpace success: total=${diskTotalSpaceMB}MB, free=${diskFreeSpaceMB}MB`);result.success(Info);} catch (err) {console.error("getDiskSpace failed with error:" + JSON.stringify(err));// 在 Flutter 端,通常期望一个 Map 或者 null/error// 这里返回一个空的 Map 或者可以考虑 result.errorresult.error("DISK_SPACE_ERROR", "Failed to get disk space", JSON.stringify(err));}} else if (call.method == "getMemoryInfo") {const Info = new Map<string, number>();// 转换为 MBconst mbFactor = 1024 * 1024;let systemMemInfo: hidebug.SystemMemInfo = hidebug.getSystemMemInfo();// Convert bigint to number before divisionInfo.set("total", Number(systemMemInfo.totalMem)/mbFactor);Info.set("free", Number(systemMemInfo.freeMem)/mbFactor);Info.set("usedByApp", Number(systemMemInfo.availableMem)/mbFactor);console.info(`totalMem: ${systemMemInfo.totalMem}, freeMem: ${systemMemInfo.freeMem}, ` +`availableMem: ${systemMemInfo.availableMem}`);//获取当前应用的存储空间大小。storageStatistics.getCurrentBundleStats((err: BusinessError, bundleStats: storageStatistics.BundleStats) => {if (err) {console.error(`Invoke getCurrentBundleStats failed, code is ${err.code}, message is ${err.message}`);} else {console.info(`Invoke getCurrentBundleStats succeeded, appsize is ${bundleStats.appSize}`);Info.set("appSize", Number(bundleStats.appSize)/mbFactor);}result.success(Info);});} else {result.notImplemented()}}
}

这里我主要参考的是

三、应用及文件系统空间统计

1.storageStatistics.getCurrentBundleStats

getCurrentBundleStats(): Promise

应用异步获取当前应用存储空间大小(单位为Byte),以Promise方式返回。

系统能力:SystemCapability.FileManagement.StorageService.SpatialStatistics

返回值:

类型说明
Promise<Bundlestats>Promise对象,返回指定卷上的应用存储空间大小(单位为Byte)。

错误码:

以下错误码的详细介绍请参见文件管理错误码

错误码ID错误信息
401The input parameter is invalid. Possible causes: Mandatory parameters are left unspecified.
13600001IPC error.
13900042Unknown error.

示例:

import { BusinessError } from '@kit.BasicServicesKit';storageStatistics.getCurrentBundleStats().then((BundleStats: storageStatistics.BundleStats) => {  console.info("getCurrentBundleStats successfully:" + JSON.stringify(BundleStats));}).catch((err: BusinessError) => {  console.error("getCurrentBundleStats failed with error:"+ JSON.stringify(err));});

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-file-storage-statistics#storagestatisticsgetfreesize15

2.应用及文件系统空间统计

在系统中,可能出现系统空间不够或者cacheDir等目录受系统配额限制等情况,需要应用开发者关注系统剩余空间,同时控制应用自身占用的空间大小。

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/app-fs-space-statistics

表1 文件系统空间和应用空间统计

模块接口名功能
@ohos.file.storageStatisticsgetCurrentBundleStats获取当前应用的存储空间大小(单位为Byte)。
@ohos.file.storageStatisticsgetFreeSize异步获取内置存储的总空间大小(单位为Byte)。
@ohos.file.storageStatisticsgetTotalSize异步获取内置存储的可用空间大小(单位为Byte)。

表2 应用空间统计

BundleStats属性含义统计路径
appSize应用安装文件大小(单位为Byte)应用安装文件保存在以下目录:/data/storage/el1/bundle
cacheSize应用缓存文件大小(单位为Byte)应用的缓存文件保存在以下目录:/data/storage/el1/base/cache/data/storage/el1/base/haps/entry/cache/data/storage/el2/base/cache/data/storage/el2/base/haps/entry/cache
dataSize应用文件存储大小(除应用安装文件和缓存文件)(单位为Byte)应用文件由本地文件、分布式文件以及数据库文件组成。本地文件保存在以下目录(注意缓存文件目录为以下目录的子目录):/data/storage/el1/base/data/storage/el2/base分布式文件保存在以下目录:/data/storage/el2/distributedfiles数据库文件保存在以下目录:/data/storage/el1/database/data/storage/el2/database

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-hidebug#hidebuggetsystemmeminfo12

3.使用 HiDebug 模块

HiDebug 提供了一系列接口,可以获取系统的内存信息,进而间接获取 RAM size 。具体步骤如下:

  • 导入 HiDebug 模块 :在代码中导入 HiDebug 模块,import { hidebug } from '@ohos.hidebug';

4.SystemMemInfo

描述系统内存信息。

系统能力:SystemCapability.HiviewDFX.HiProfiler.HiDebug

名称类型必填说明
totalMembigint系统总的内存,以KB为单位,计算方式:/proc/meminfo: MemTotal。
freeMembigint系统空闲的内存,以KB为单位,计算方式:/proc/meminfo: MemFree。
availableMembigint系统可用的内存,以KB为单位,计算方式:/proc/meminfo: MemAvailable
  • usedByApp: 表示当前应用程序占用的内存大小(单位:MB)。这是通过 Runtime 类计算得到的应用已分配内存减去其中的空闲内存。
  • total: 表示设备的总内存(RAM)大小(单位:MB)。这是通过 ActivityManager.MemoryInfo 获取的系统总内存。
  • free: 表示设备当前可用的内存大小(单位:MB)。这是通过 ActivityManager.MemoryInfo 获取的系统可用内存,指系统在开始强制关闭后台进程之前可用的内存。
  • lowMemory: 一个布尔值,表示系统当前是否处于低内存状态。如果为 true,则表示系统内存不足。

5.appManager.isRamConstrainedDevice7+

isRamConstrainedDevice(): Promise

查询是否为ram受限设备。使用Promise异步回调。

系统能力:SystemCapability.Ability.AbilityRuntime.Core

返回值:

类型说明
PromisePromise对象。返回true表示是ram受限设备;返回false表示不是ram受限设备。

示例:

import appManager from '@ohos.application.appManager';import { BusinessError } from '@ohos.base';
appManager.isRamConstrainedDevice().then((data) => {    console.log(`The result of isRamConstrainedDevice is: ${JSON.stringify(data)}`);}).catch((error: BusinessError) => {    console.error(`error: ${JSON.stringify(error)}`);});

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-application-appmanager

6.appManager.isRamConstrainedDevice7+

isRamConstrainedDevice(callback: AsyncCallback): void

查询是否为ram受限设备。使用callback异步回调。

系统能力:SystemCapability.Ability.AbilityRuntime.Core

参数:

参数名类型必填说明
callbackAsyncCallback回调函数。返回true表示当前是ram受限设备;返回false表示当前不是ram受限设备。

示例:

import appManager from '@ohos.application.appManager';
appManager.isRamConstrainedDevice((error, data) => {    if (error && error.code !== 0) {        console.error(`isRamConstrainedDevice fail, error: ${JSON.stringify(error)}`);    } else {        console.log(`The result of isRamConstrainedDevice is: ${JSON.stringify(data)}`);    }});

7.使用 HiDebug 模块

HiDebug 提供了一系列接口,可以获取系统的内存信息,进而间接获取 RAM size 。具体步骤如下:

  • 导入 HiDebug 模块 :在代码中导入 HiDebug 模块,import { hidebug } from '@ohos.hidebug';
  • 调用接口获取内存信息 :调用 hidebug.getSystemMemInfo() 接口获取系统内存信息,该方法返回一个对象,其中包含了系统的总内存、可用内存等信息。

https://github.com/SebghatYusuf/system_info_plus

四、编写 Example

1. 创建 Example 应用

在插件根目录下创建一个名为 example 的文件夹,用于存放示例应用。在 example 文件夹中,创建一个鸿蒙平台的 Flutter 应用,用于验证插件功能。

2. 签名与运行

使用 Deveco Studio 打开 example > ohos 目录,单击 File > Project Structure > Project > Signing Configs,勾选 Automatically generate signature,等待自动签名完成。然后运行以下命令:

flutter pub getflutter build hap --debug

如果应用正常启动,说明插件适配成功。如果没有,欢迎大家联系坚果派一起支持。

五、总结

通过以上步骤,我们成功地将 memory_info 三方库适配到了鸿蒙平台。这个过程涉及到了解插件的基本信息、配置开发环境、创建鸿蒙模块、编写原生代码以及测试验证等多个环节。希望这篇博客能够帮助到需要进行 memory_info可帮助您获取设备内存信息(ram&rom) 鸿蒙适配的开发者们,让大家在鸿蒙生态的开发中更加得心应手。

六、参考

  • [如何使用Flutter与OpenHarmony通信 FlutterChannel](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8Flutter%E4%B8%8EOpenHarmony%E9%80%9A%E4%BF%A1 FlutterChannel.md)
  • [开发module](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E6%B7%B7%E5%90%88%E5%BC%80%E5%8F%91 module.md)
  • 开发package
  • 开发plugin
  • [开发FFI plugin](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/%E5%BC%80%E5%8F%91FFI plugin.md)
  • developing-packages
  • 适配仓库地址

相关文章:

  • 本地测试远程DM达梦数据库连接(使用DBeaver)
  • 砷化镓太阳能电池:开启多元领域能源新篇
  • 印刷业直角坐标型码垛机器人系统设计与应用研究
  • sql server 2019 将单用户状态修改为多用户状态
  • C++学习之打车软件git版本控制
  • React Native矢量图标全攻略:从入门到自定义iconfont的高级玩法
  • 【AAAI 2025】 Local Conditional Controlling for Text-to-Image Diffusion Models
  • 算法每日刷题 Day6 5.14:leetcode数组1道题,用时30min,明天按灵茶山艾府题单开刷,感觉数组不应该单算
  • hbase shell的常用命令
  • Kubernetes控制平面组件:Kubelet详解(三):CRI 容器运行时接口层
  • 【unity游戏开发——编辑器扩展】使用EditorGUI的EditorGUILayout绘制工具类在自定义编辑器窗口绘制各种UI控件
  • iOS Safari调试教程
  • DeepSeek:AI助力高效工作与智能管理
  • 作业帮Android面试题及参考答案
  • Java面试八股Spring篇(4500字)
  • Python如何解决中文乱码
  • Linux——CMake的快速入门上手和保姆级使用介绍、一键执行shell脚本
  • # 深度剖析LLM的“大脑”:单层Transformer的思考模式探索
  • 【数据库复习】SQL语言
  • 联邦+反射器 基础实验
  • 汤加附近海域发生6.4级地震
  • 中哥两国元首共同见证签署《中华人民共和国政府与哥伦比亚共和国政府关于共同推进丝绸之路经济带和21世纪海上丝绸之路建设的合作规划》
  • 习近平举行仪式欢迎巴西总统卢拉访华
  • 马上评丨摆摊要交芙蓉王?对吃拿卡要必须零容忍
  • 西藏日喀则市拉孜县发生5.5级地震,震源深度10公里
  • 马克龙称法英正与乌克兰商议“在乌部署欧洲军队”