Flutter三方库适配OpenHarmony【apple_product_name】库简介与功能概述
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
在移动应用开发中,获取设备的友好名称 是一个非常常见且重要的需求。当用户打开"关于手机"页面或提交问题反馈时,他们更希望看到"HUAWEI Mate 60 Pro"这样直观的产品名称,而不是"ALN-AL00"这样晦涩的型号标识符。apple_product_name 库正是为解决这一痛点而诞生的,它最初用于将Apple设备标识符转换为产品名称,在OpenHarmony适配版本中,这一能力被扩展到了华为和荣耀系列设备。本文将全面介绍该库在OpenHarmony平台的功能特性、架构设计和使用方式。
本文是apple_product_name OpenHarmony适配系列的第1篇,共30篇,从入门到源码分析全面覆盖该库的使用方法。
一、库的基本信息
1.1 pubspec.yaml配置
yaml
name: apple_product_name
description: Library for translating Apple machine identifiers into Apple product names
version: 3.7.0
homepage: https://github.com/kyle-seongwoo-jun/flutter_apple_product_name
environment:
sdk: ">=3.5.0 <4.0.0"
flutter: ">=3.22.0"
dependencies:
flutter:
sdk: flutter
device_info_plus: ">=10.0.0 <12.0.0"
以上是该库在pubspec.yaml中的完整配置。库名虽然包含"Apple",但OpenHarmony适配版本 已全面扩展到华为和荣耀设备。当前版本3.7.0,依赖device_info_plus获取Apple设备信息,鸿蒙平台则通过自己的MethodChannel实现。
1.2 项目基本信息总览
| 项目 | 说明 |
|---|---|
| 库名 | apple_product_name |
| 当前版本 | 3.7.0 |
| 许可证 | MIT |
| 原始作者 | kyle-seongwoo-jun |
| 原始仓库 | GitHub |
| OpenHarmony适配 | GitCode oh-flutter |
| Dart SDK | >=3.5.0 <4.0.0 |
| Flutter SDK | >=3.22.0 |
| 鸿蒙IDE | DevEco Studio 6.0.2 Release |
| OpenHarmony SDK | API 20 |
该库采用MIT许可证 ,允许自由使用、修改和分发。原始库面向iOS/macOS平台,OpenHarmony适配版本由开源鸿蒙跨平台社区维护,增加了ArkTS原生插件和华为设备映射表。
1.3 库的核心能力
该库提供以下核心能力:
- 设备名称转换:将型号标识符(如"ALN-AL00")转换为友好名称(如"HUAWEI Mate 60 Pro")
- 多平台支持:同时支持iOS、macOS和OpenHarmony三个平台
- 丰富的映射表:内置90+华为/荣耀设备映射数据
- 降级策略:映射表未收录时自动回退到系统marketName
注意:该库的OpenHarmony适配版本目前通过Git依赖引入,尚未发布到pub.dev官方仓库。
二、整体架构设计
2.1 多平台运行效果
下图展示了该库在iOS和macOS平台的运行效果:

上图是iOS平台的运行截图,展示了iPhone设备的产品名称识别效果。

上图是macOS平台的运行截图,展示了Mac设备的产品名称识别效果。在OpenHarmony平台上,运行效果类似,会显示如"HUAWEI Mate 60 Pro"这样的华为设备名称。
2.2 项目目录结构预览
下图展示了项目在DevEco Studio中的目录结构:

上图展示了项目的整体文件组织方式,lib/目录存放Dart层代码,ohos/目录存放ArkTS原生插件代码。
2.3 OpenHarmony平台架构
在OpenHarmony平台上,整体架构分为三层:
┌─────────────────────────────────────────────────┐
│ Flutter App │
│ ┌───────────────────────────────────────────┐ │
│ │ OhosProductName (Dart) │ │
│ │ getProductName() / getMachineId() / lookup│ │
│ └──────────────────┬────────────────────────┘ │
│ │ MethodChannel │
│ │ "apple_product_name" │
│ ┌──────────────────▼────────────────────────┐ │
│ │ AppleProductNamePlugin (ArkTS) │ │
│ │ ┌─────────────┐ ┌───────────────────┐ │ │
│ │ │ deviceInfo │ │ HUAWEI_DEVICE_MAP │ │ │
│ │ │ .productModel│ │ (映射表查找) │ │ │
│ │ └─────────────┘ └───────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
│ OpenHarmony OS │
└─────────────────────────────────────────────────┘
三层架构的职责划分:
- Flutter应用层 :通过
OhosProductName类提供Dart API - MethodChannel通信层:负责Dart与原生层的跨平台消息传递
- ArkTS原生插件层 :通过
deviceInfo系统API获取设备型号,在HUAWEI_DEVICE_MAP映射表中查找友好名称
2.4 核心文件结构
├── lib/
│ ├── apple_product_name.dart # Apple设备查询API
│ ├── apple_product_name.g.dart # 自动生成的Apple设备映射表
│ └── apple_product_name_ohos.dart # 鸿蒙平台API(OhosProductName类)
├── ohos/
│ ├── oh-package.json5 # 鸿蒙包配置
│ ├── index.ets # 插件导出入口
│ └── src/main/ets/components/plugin/
│ └── AppleProductNamePlugin.ets # 原生插件实现+设备映射表
├── example/ # 示例应用
├── gen/ # Apple映射表生成脚本
└── test/ # 单元测试
开发者日常使用只需关注以下两个文件:
lib/apple_product_name_ohos.dart:Dart层API入口ohos/.../AppleProductNamePlugin.ets:原生层插件实现和设备映射表
三、OpenHarmony适配版本的获取
3.1 依赖配置
yaml
dependencies:
apple_product_name:
git:
url: https://gitcode.com/oh-flutter/flutter_apple_product_name.git
ref: main
由于OpenHarmony适配版本尚未发布到pub.dev官方仓库,需要通过Git依赖引入。使用ref: main指定主分支最新代码,确保获取最新的设备映射数据。在生产项目中,如果需要锁定版本,可以将ref指向具体的tag或commit hash。
3.2 鸿蒙平台插件声明
yaml
flutter:
plugin:
platforms:
ohos:
pluginClass: AppleProductNamePlugin
pubspec.yaml中通过flutter.plugin.platforms.ohos声明了鸿蒙平台的插件入口类为AppleProductNamePlugin。Flutter框架在应用启动时会根据这个配置自动加载并注册原生插件。
3.3 鸿蒙包配置
json5
{
"name": "apple_product_name",
"version": "1.0.0",
"description": "Library for translating Apple machine identifiers into Apple product names for OpenHarmony.",
"main": "index.ets",
"license": "MIT",
"dependencies": {
"@ohos/flutter_ohos": "file:./har/flutter.har"
}
}
ohos/oh-package.json5定义了鸿蒙包的元信息,main字段指向index.ets入口文件,@ohos/flutter_ohos是鸿蒙Flutter引擎的本地依赖。
四、核心API详解
4.1 OhosProductName类
OhosProductName 是鸿蒙平台的核心入口类,采用单例模式设计:
dart
class OhosProductName {
static const MethodChannel _channel = MethodChannel('apple_product_name');
static final _instance = OhosProductName._();
OhosProductName._();
factory OhosProductName() => _instance;
}
通过私有构造函数和工厂构造函数实现单例,无论在应用任何地方调用OhosProductName(),返回的都是同一个实例。单例模式的优势:
- 避免重复创建对象带来的内存浪费
- 保证MethodChannel通信通道的唯一性
- 简化使用方式,无需手动管理实例生命周期
4.2 三个核心方法
该类提供了三个核心方法,覆盖了设备信息获取的所有场景:
dart
/// 获取设备产品名称,例如: "HUAWEI Mate 60 Pro"
Future<String> getProductName() async {
final String? productName = await _channel.invokeMethod('getProductName');
return productName ?? 'Unknown';
}
/// 获取设备型号标识符,例如: "ALN-AL00"
Future<String> getMachineId() async {
final String? machineId = await _channel.invokeMethod('getMachineId');
return machineId ?? 'Unknown';
}
/// 根据型号标识符查找产品名称
Future<String> lookup(String machineId) async {
final String? productName = await _channel.invokeMethod('lookup', {
'machineId': machineId,
});
return productName ?? machineId;
}
三个方法的功能对比:
| 方法 | 功能 | 返回值示例 | 典型使用场景 |
|---|---|---|---|
getProductName() |
获取当前设备友好名称 | "HUAWEI Mate 60 Pro" | 设备信息展示、关于页面 |
getMachineId() |
获取当前设备型号标识符 | "ALN-AL00" | 日志记录、问题排查 |
lookup(id) |
查询任意型号的产品名称 | 产品名称或原始id | 批量数据分析、客服系统 |
关键点 :所有方法都是异步的,通过MethodChannel与原生层通信,返回值都做了null安全处理 (
??兜底),确保调用方始终拿到非空结果。
4.3 lookupOrNull方法
除了上述三个核心方法,还有一个返回可空类型的查询方法:
dart
/// 返回产品名称,如果未找到则返回 null
Future<String?> lookupOrNull(String machineId) async {
final String? productName = await _channel.invokeMethod('lookup', {
'machineId': machineId,
});
return productName;
}
lookupOrNull与lookup的区别在于:未找到映射时返回null而非原始machineId。这在需要区分"已知设备"和"未知设备"的场景中非常有用。
五、原生层实现原理
5.1 插件入口与导出
ohos/index.ets是插件的导出入口:
typescript
import AppleProductNamePlugin from './src/main/ets/components/plugin/AppleProductNamePlugin';
export default AppleProductNamePlugin;
export { AppleProductNamePlugin };
5.2 getProductName的原生实现
当Dart层调用getProductName()时,原生层的处理逻辑如下:
typescript
private getProductName(result: MethodResult): void {
try {
const model = deviceInfo.productModel;
// 先从映射表查找
let productName = HUAWEI_DEVICE_MAP[model];
// 如果映射表没有,使用系统的 marketName
if (!productName) {
productName = deviceInfo.marketName || model;
}
result.success(productName);
} catch (e) {
const errorMsg = e instanceof Error ? e.message : String(e);
result.error("GET_PRODUCT_NAME_ERROR", errorMsg, null);
}
}
这是一个两级查找策略:
- 首先通过
deviceInfo.productModel获取型号标识符(如"ALN-AL00") - 在
HUAWEI_DEVICE_MAP映射表中查找友好名称 - 如果映射表未收录,回退到系统
marketName字段 - 最后兜底返回原始型号
设计亮点:这种降级策略确保即使遇到映射表尚未收录的新设备,也不会返回空值,用户始终能看到有意义的设备信息。
5.3 数据流转全链路
从用户调用到UI展示的完整数据流:
用户调用 OhosProductName().getProductName()
→ Dart层: _channel.invokeMethod('getProductName')
→ MethodChannel序列化消息
→ ArkTS层: onMethodCall() 路由到 getProductName()
→ 读取 deviceInfo.productModel (如 "ALN-AL00")
→ 查找 HUAWEI_DEVICE_MAP["ALN-AL00"]
→ 返回 "HUAWEI Mate 60 Pro"
→ result.success() → MethodChannel返回
→ Dart层 Future<String> 完成
→ UI展示 "HUAWEI Mate 60 Pro"
整个链路涉及Dart异步调用、MethodChannel跨平台消息序列化、原生层设备API调用和映射表查找,通常在毫秒级完成。
六、支持的设备范围
6.1 设备系列总览
映射表HUAWEI_DEVICE_MAP覆盖了以下设备系列:
| 设备系列 | 代表型号 | 型号数量 | 说明 |
|---|---|---|---|
| Mate系列 | Mate 70/60/X5/X3 | 22个 | 旗舰手机+折叠屏 |
| Pura系列 | Pura 70/P60 | 12个 | 影像旗舰(原P系列) |
| nova系列 | nova 13/12/11 | 14个 | 年轻时尚系列 |
| Pocket系列 | Pocket 2/Pocket S | 4个 | 小折叠屏 |
| MatePad系列 | MatePad Pro/Air | 10个 | 平板设备 |
| 荣耀Magic | Magic6/Magic5 | 8个 | 荣耀旗舰 |
| 荣耀数字 | Honor 200/100 | 8个 | 荣耀中端 |
| 华为手表 | WATCH GT/Ultimate | 12个 | 智能手表 |
6.2 映射表代码片段
typescript
const HUAWEI_DEVICE_MAP: Record<string, string> = {
// Mate 70 系列
"CFR-AN00": "HUAWEI Mate 70",
"CFS-AN00": "HUAWEI Mate 70 Pro",
"CFT-AN00": "HUAWEI Mate 70 Pro+",
"CFU-AN00": "HUAWEI Mate 70 RS 非凡大师",
// Pura 70 系列
"HBN-AL00": "HUAWEI Pura 70",
"DUA-AL00": "HUAWEI Pura 70 Pro",
"HBK-AL00": "HUAWEI Pura 70 Ultra",
// nova 系列
"FOA-AL00": "HUAWEI nova 13",
"FNA-AL00": "HUAWEI nova 13 Pro",
// 荣耀系列
"PGT-AN00": "Honor Magic6 Pro",
"BVL-AN00": "Honor Magic6",
// ... 共90+个型号映射
};
映射表按设备系列分组,每个键值对的键是deviceInfo.productModel返回的型号标识符,值是华为官方的市场命名。映射表会随新设备发布持续更新,社区开发者也可以通过提交Pull Request贡献新设备数据。
6.3 型号命名规则
华为设备型号标识符遵循统一的命名规则:
| 组成部分 | 示例 | 含义 |
|---|---|---|
| 产品代号 | ALN | 产品唯一标识(如Mate 60 Pro) |
| 分隔符 | - | 固定连字符 |
| 网络制式 | AL | 国内全网通版本 |
| 版本号 | 00 | 标准版本 |
常见后缀含义:
- AL/AN:国内全网通版本
- LX:国际版本
- W:WiFi版本(平板/折叠屏)
- 80:高配版本(如Pro+/Art/Ultra)
七、实际应用示例
7.1 基础用法
dart
import 'package:apple_product_name/apple_product_name_ohos.dart';
// 获取设备产品名称
final productName = await OhosProductName().getProductName();
print(productName); // "HUAWEI Pura 70 Ultra"
// 获取设备型号标识符
final machineId = await OhosProductName().getMachineId();
print(machineId); // "HBK-AL00"
// 查询任意型号
final name = await OhosProductName().lookup('ALN-AL00');
print(name); // "HUAWEI Mate 60 Pro"
三行代码即可完成设备信息获取,API设计简洁直观。所有方法都是异步的,需要使用await等待结果。
7.2 在Flutter页面中使用
以下是项目example应用 中的实际代码(来自example/lib/main.dart):
dart
import 'dart:io';
import 'package:apple_product_name/apple_product_name.dart';
import 'package:apple_product_name/apple_product_name_ohos.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
Future<String> _loadProductName() async {
if (Platform.isIOS) {
final info = await DeviceInfoPlugin().iosInfo;
return info.utsname.productName;
} else if (Platform.isMacOS) {
final info = await DeviceInfoPlugin().macOsInfo;
return info.productName;
} else {
// 鸿蒙平台
try {
return await OhosProductName().getProductName();
} catch (e) {
return 'Unknown';
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Apple Product Name')),
body: FutureBuilder<String>(
future: _loadProductName(),
builder: (context, snapshot) {
final productName = snapshot.data ?? 'Loading...';
return Center(
child: Text(productName,
style: Theme.of(context).textTheme.headlineSmall!
.copyWith(color: Colors.black)),
);
},
),
),
);
}
}
这段代码展示了跨平台 的使用方式:通过Platform判断当前平台,iOS/macOS使用device_info_plus,鸿蒙平台使用OhosProductName。FutureBuilder处理异步加载状态,数据未返回时显示"Loading...",返回后展示产品名称。
八、与其他方案的对比
8.1 为什么不直接使用系统API
| 对比项 | 直接使用deviceInfo | 使用apple_product_name |
|---|---|---|
| 返回值 | "ALN-AL00"(型号标识符) | "HUAWEI Mate 60 Pro"(友好名称) |
| 可读性 | 低,用户无法理解 | 高,用户一目了然 |
| 维护成本 | 需要自己维护映射表 | 库内置90+设备映射 |
| 降级策略 | 无 | 映射表→marketName→原始型号 |
| 跨平台 | 需要分平台处理 | 统一API,一套代码 |
直接调用deviceInfo.productModel只能拿到原始型号标识符,对用户毫无意义。apple_product_name库封装了完整的映射逻辑和降级策略,开发者无需关心底层细节。
8.2 适用场景
该库适用于以下典型场景:
dart
// 场景1:设备信息展示页面
final name = await OhosProductName().getProductName();
showDialog(context: context, builder: (_) => AlertDialog(
title: Text('当前设备'),
content: Text(name), // "HUAWEI Mate 70 Pro"
));
// 场景2:用户反馈自动附带设备信息
final feedback = {
'content': userInput,
'device': await OhosProductName().getProductName(),
'model': await OhosProductName().getMachineId(),
};
// 场景3:崩溃日志中记录设备型号
try {
// 业务代码
} catch (e) {
logger.error('Crash on ${await OhosProductName().getProductName()}: $e');
}
无论是面向用户的信息展示,还是面向开发者的日志分析,该库都能提供清晰可读的设备名称。
九、环境要求与版本兼容
9.1 开发环境要求
| 环境项 | 最低版本 | 推荐版本 |
|---|---|---|
| Dart SDK | 3.5.0 | 3.5.0+ |
| Flutter SDK | 3.22.0 | 3.22.0+ |
| Flutter OHOS | 3.35.7-dev | 3.35.7-dev |
| DevEco Studio | 6.0.2 Release | 6.0.2 Release |
| OpenHarmony SDK | API 20 | API 20 |
| ROM | 6.0.0.130 SP8 | 6.0.0.130 SP8 |
9.2 环境验证
bash
# 验证Flutter环境
flutter doctor
# 验证Dart版本
dart --version
# 预期输出:Dart SDK version: 3.5.x
运行flutter doctor可以检查所有必要工具和SDK是否正确安装。如果报告问题,需要逐一解决后再开始开发。
详细的环境搭建步骤将在第2篇:环境搭建与依赖配置中介绍。
9.3 快速验证安装
安装完成后,可以用以下代码快速验证库是否正常工作:
dart
import 'package:apple_product_name/apple_product_name_ohos.dart';
void main() async {
final ohos = OhosProductName();
print('设备名称: ${await ohos.getProductName()}');
print('型号标识: ${await ohos.getMachineId()}');
print('查询测试: ${await ohos.lookup("ALN-AL00")}');
}
如果三个方法都能正常返回结果,说明库已经正确集成。
十、系列文章导航
本系列共30篇文章,从入门到源码分析全面覆盖:
| 篇章 | 主题 | 内容概要 |
|---|---|---|
| 第1-3篇 | 入门篇 | 库简介、环境搭建、快速上手 |
| 第4-10篇 | API篇 | OhosProductName类、各方法详解、异步处理 |
| 第11-15篇 | 映射表篇 | Mate/Pura/nova/MatePad/荣耀设备映射 |
| 第16-22篇 | 源码篇 | 插件架构、源码分析、MethodChannel机制 |
| 第23-29篇 | 实战篇 | 页面构建、反馈系统、统计分析、性能优化 |
| 第30篇 | 生态篇 | 源码贡献与生态共建 |
推荐阅读顺序:
- 先阅读第1-3篇完成入门
- 再阅读第4-10篇掌握API用法
- 根据需要选读映射表篇、源码篇或实战篇
总结
apple_product_name 库的OpenHarmony适配版本通过MethodChannel架构 和内置的90+设备映射表 ,为Flutter开发者提供了便捷的设备名称获取能力。三个核心API(getProductName、getMachineId、lookup)覆盖了设备信息展示、日志分析、数据统计等所有常见场景,两级查找策略确保了在任何设备上都能返回有意义的结果。
下一篇文章将介绍环境搭建与依赖配置。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- OpenHarmony适配仓库:https://gitcode.com/oh-flutter/flutter_apple_product_name
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
- 原始GitHub仓库:https://github.com/kyle-seongwoo-jun/flutter_apple_product_name
- device_info_plus:https://pub.dev/packages/device_info_plus
- Flutter官方文档:https://flutter.dev
- OpenHarmony官方文档:https://www.openharmony.cn