DeviceInfoService 核心设计解析:HarmonyOS 设备信息采集为什么要工程化

摘要

CheckMe 项目里,真正的数据底座不是页面,也不是卡片,而是 DeviceInfoService。它负责统一采集 CPU、内存、存储、电池、网络、传感器、屏幕等信息,并向页面和卡片提供统一的数据入口。本文将围绕这个服务层模块,讲清楚为什么要把设备信息采集做成统一架构,以及它在真实项目里能解决哪些问题。

四个主题适配说明

这篇文章的主方向是 能力增强,因为 DeviceInfoService 把 BasicServicesKit、NetworkKit、SensorServiceKit、文件系统读取等能力统一封装成项目数据底座。它同时符合 安全隐私,因为受限数据不伪造、失败值集中兜底、敏感能力按边界处理;符合 高端精致,因为统一数据口径能让页面和卡片展示更稳定、更可信;符合 创新体验,因为同一套数据可以同时服务主页面、工具页和桌面卡片,形成多入口体验。

一、为什么设备信息类项目最容易写乱

设备信息类应用有一个很典型的问题:功能看上去不复杂,但代码极容易散。

比如你很可能一开始只是想做一个 CPU 页面,然后:

  • 页面 A 想显示 CPU 信息
  • 页面 B 想显示内存信息
  • 概览页又要同时显示 CPU、存储、电池
  • 服务卡片也想拿这些信息
  • 后台刷新时还要重新采集一次

如果每个页面都直接去调用系统 API,很快就会出现:

  • 逻辑重复
  • 字段不统一
  • 错误处理不一致
  • 页面层和能力层耦合

所以我在做 CheckMe 时,很早就决定把采集逻辑统一沉到一个服务层里,这就是 DeviceInfoService

二、DeviceInfoService 在项目中的定位

它的核心职责是:

  1. 统一接入多个 HarmonyOS 能力源。
  2. 屏蔽底层调用细节。
  3. 返回统一的数据模型。
  4. 为不同页面、卡片和后台任务提供可复用的数据入口。

用一句话概括就是:

页面只管要什么,Service 负责决定怎么拿。

三、这个服务统一接了哪些能力

从代码里可以看到,DeviceInfoService 集成了不少系统能力:

  • @kit.BasicServicesKit
  • @kit.SensorServiceKit
  • @kit.NetworkKit
  • @ohos.display
  • @ohos.file.fs
  • @ohos.hidebug

这些能力分别提供:

  • 设备基础信息
  • 电池信息
  • 传感器信息
  • 网络信息
  • 屏幕信息
  • 系统性能信息
  • 文件系统读取能力

如果不做服务层封装,这些调用会散落在整个项目里,非常难维护。

四、统一入口为什么很重要

DeviceInfoService 里,有一个很典型的总入口:

public async getDeviceInfo(): Promise<DeviceInfoData> {
  const cpuInfo: CpuInfo = await this.getCpuInfo();
  const memoryInfo: MemoryInfo = await this.getMemoryInfo();
  const screenInfo: ScreenInfo = await this.getScreenInfo();
  const batteryInfoData: BatteryInfo | null = await this.getBatteryInfo();
  const storageInfo: StorageInfo = await this.getStorageInfo();
  const gpuInfo: GpuInfo = await this.getGpuInfo();
  const cameraInfo: CameraInfo[] = await this.getCameraInfo();
  const sensorInfo: SensorInfo[] = await this.getSensorInfo();
  const networkInfo: NetworkInfo | null = await this.getNetworkInfo();
  ...
}

这段代码的价值在于,它把“零散信息采集”变成了“结构化数据汇总”。

例如概览页如果想展示一组完整设备信息,只要拿这个总对象就行,而不需要逐个理解 CPU、网络、传感器到底怎么获取。

五、为什么 Service 层还能帮助统一数据质量

项目里很多信息并不是调用一个 API 就百分百稳定拿到的。真实情况是:

  • 有的字段可能在某些设备上为空
  • 有的能力在 HarmonyOS NEXT 第三方应用环境下受限制
  • 有的系统文件可能读不到
  • 有的值可能需要二次整理和推断

这时候 Service 层最大的价值之一,就是统一兜底策略。

比如在 getDeviceBasicInfo() 里,项目会对品牌、型号、制造商等字段做默认值回退,确保页面拿到的数据尽可能可展示,而不是直接出现空白或崩溃。

这类逻辑如果散在页面层,不仅难看,还会很难统一。

六、为什么在设备信息项目里,页面不应该直接碰系统能力

很多初学者喜欢在页面里直接写:

  • 拿 CPU
  • 拿内存
  • 拿网络
  • 然后当场显示

这种写法的问题是:

1. 页面职责被污染

页面本来应该关注状态展示和交互,而不是底层能力接入。

2. 复用性差

当卡片、详情页、概览页都想要 CPU 信息时,重复逻辑会越来越多。

3. 难以测试和替换

如果以后想调整 CPU 读取方式,或者增加缓存策略,所有页面都得改。

所以 DeviceInfoService 的存在,实际上是整个项目工程化程度的核心体现。

七、CPU、网络、内存这些信息是如何分层获取的

1. CPU 信息

CPU 是整个项目里最复杂的一类信息。因为它既涉及:

  • 核心数
  • 当前使用率
  • 当前频率
  • 最大频率
  • 核心类型

其中一些来自 HarmonyOS 可直接调用的能力,一些则需要配合 CpuInfoReader.ts 和 Native 层继续补强。

2. 内存信息

内存信息主要通过系统能力读取,再做统一标准化,确保不同入口拿到的数据口径一致。

3. 网络信息

网络模块不仅要判断是否连接,还要识别网络类型、信号强度、链路参数等。这类信息非常适合收口到 Service 层,因为卡片、主页和工具页经常会重复用到。

4. 存储信息

存储不只是显示总容量和已用容量,项目中还结合了 StorageCalibrationStore 做校准相关处理,这也是“单页直写”很难优雅完成的工作。

八、Service 层和 WidgetDataService 的分工是什么

有些同学会问,既然已经有了 DeviceInfoService,为什么还要再做一个 WidgetDataService

原因在于它们职责不同:

DeviceInfoService

  • 面向原始设备能力
  • 负责采集与统一结构

WidgetDataService

  • 面向卡片展示需求
  • 负责缓存、历史数组、轻量展示模型

举个例子:

  • DeviceInfoService 负责拿到 CPU 使用率和每核频率
  • WidgetDataService 再把它们整理成 usageHistorycoreTypesavgFreq 等更适合卡片渲染的字段

这种分层非常适合真实项目,因为它避免了一个 Service 什么都做,越写越臃肿。

九、设备信息项目里,为什么要慎重处理“拿不到”的数据

这一点我特别想强调。

DeviceInfoService.ts 中,我并没有为了“看起来功能很全”就强行拼凑不可靠结果。比如:

  • 某些受限能力不直接伪造值
  • 拿不到运营商信息时不瞎猜
  • 失败时返回空值或保守结构,而不是错误信息直接冒到 UI

这类处理非常适合“安全隐私”和“专业性”表达。因为一个好的设备信息项目,最重要的不是“把一切都显示出来”,而是“显示真实、稳定、可解释的数据”。

十、这个 Service 在项目扩展上带来了什么好处

CheckMe 现在不只有一个概览页,它还有:

  • 服务卡片
  • 位置页
  • 工具页
  • 存储分析
  • 设备诊断

如果没有统一服务层,后面每扩一个模块,都会重复接底层能力。但有了 DeviceInfoService 之后,很多功能只是“换个展示方式”而已,不需要再重写一遍采集逻辑。

这也是为什么我说,DeviceInfoService 不是配角,而是整个项目最核心的工程模块之一。

十一、做这种服务层最容易踩的坑

1. 把页面逻辑写进 Service

解决:Service 只负责数据采集和整理,不负责 UI 语义。

2. 一个方法返回的数据口径不统一

解决:定义统一模型,例如 DeviceInfoDataCpuInfoMemoryInfo

3. 不做错误兜底

解决:在 Service 层集中处理异常和默认值。

4. 不区分原始数据和展示数据

解决:原始能力归 DeviceInfoService,展示模型归上层或专用 Service。

十二、结语

如果说 AdvancedDashboard 代表项目的视觉表现,WidgetFormAbility 代表项目的卡片能力,那么 DeviceInfoService 就代表这个项目真正的工程底座。

它让 CheckMe 从一组页面,变成了一套有统一数据入口、统一能力封装、统一错误处理和统一扩展方式的完整工程。对于任何想做工具类、监控类 HarmonyOS 项目的开发者来说,这都是非常值得优先打磨的一层。
在这里插入图片描述

Logo

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

更多推荐