Flutter三方库适配OpenHarmony【apple_product_name】库简介与功能概述

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 库的核心能力

该库提供以下核心能力:

  1. 设备名称转换:将型号标识符(如"ALN-AL00")转换为友好名称(如"HUAWEI Mate 60 Pro")
  2. 多平台支持:同时支持iOS、macOS和OpenHarmony三个平台
  3. 丰富的映射表:内置90+华为/荣耀设备映射数据
  4. 降级策略:映射表未收录时自动回退到系统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(),返回的都是同一个实例。单例模式的优势:

  1. 避免重复创建对象带来的内存浪费
  2. 保证MethodChannel通信通道的唯一性
  3. 简化使用方式,无需手动管理实例生命周期

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;
}

lookupOrNulllookup的区别在于:未找到映射时返回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);
  }
}

这是一个两级查找策略

  1. 首先通过deviceInfo.productModel获取型号标识符(如"ALN-AL00")
  2. HUAWEI_DEVICE_MAP映射表中查找友好名称
  3. 如果映射表未收录,回退到系统marketName字段
  4. 最后兜底返回原始型号

设计亮点:这种降级策略确保即使遇到映射表尚未收录的新设备,也不会返回空值,用户始终能看到有意义的设备信息。

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,鸿蒙平台使用OhosProductNameFutureBuilder处理异步加载状态,数据未返回时显示"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. 先阅读第1-3篇完成入门
  2. 再阅读第4-10篇掌握API用法
  3. 根据需要选读映射表篇、源码篇或实战篇

总结

apple_product_name 库的OpenHarmony适配版本通过MethodChannel架构 和内置的90+设备映射表 ,为Flutter开发者提供了便捷的设备名称获取能力。三个核心API(getProductNamegetMachineIdlookup)覆盖了设备信息展示、日志分析、数据统计等所有常见场景,两级查找策略确保了在任何设备上都能返回有意义的结果。

下一篇文章将介绍环境搭建与依赖配置。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
sdff113962 小时前
【HarmonyOS】Flutter实战项目+校园通服务平台全解
flutter·华为·harmonyos
lqj_本人2 小时前
Flutter三方库适配OpenHarmony【apple_product_name】lookup查询方法使用技巧
flutter
lqj_本人3 小时前
Flutter三方库适配OpenHarmony【apple_product_name】设备型号标识符转换原理
运维·服务器·flutter
lqj_本人3 小时前
Flutter三方库适配OpenHarmony【apple_product_name】getMachineId方法深度解析
flutter
2401_892000523 小时前
Flutter for OpenHarmony 猫咪管家App实战:急救指南功能开发
flutter
钛态3 小时前
Flutter for OpenHarmony 实战:Pretty Dio Logger — 网络请求监控利器
flutter·microsoft·ui·华为·架构·harmonyos
lqj_本人4 小时前
Flutter三方库适配OpenHarmony【apple_product_name】OhosProductName类使用详解
flutter
lqj_本人4 小时前
Flutter三方库适配OpenHarmony【apple_product_name】异步调用与错误处理
flutter
哈__4 小时前
基础入门 Flutter for OpenHarmony:animations 动画组件详解
flutter