Flutter 三方库「plugin-Color-FromHex」的鸿蒙化适配指南,适配HarmonyOS支持把十六进制颜色字符串转成 Flutter 的 Color 对象
开发工具: 华为云码道
本文配套仓库: 上游 DHY-SOLUTIONS/plugin-Color-FromHex;鸿蒙适配改动已提交到本地
master分支。
鸿蒙适配后仓库:https://atomgit.com/oh-flutter/plugin-Color-FromHex
color_from_hex 是一个轻量的 Flutter 颜色工具库,提供十六进制颜色字符串与 Color 的双向转换,以及颜色亮度判断能力。本文以 color_from_hex 0.0.3 为例,介绍源码准备、OHOS 工程配置、ArkTS 实现和 example 真机运行。
插件目前支持 ohos 平台,源码位于 GitHub 配套仓库。文中的代码以提交 b655fdac43509a5cde80d4f2e4eea68d3f2336ac(feat: adapt color_from_hex to OpenHarmony)为参考。

OHOS 适配https://atomgit.com/oh-flutter/plugin-Color-FromHex改动当前在 main 分支工作区,发布 TAG 为 0.0.3-ohos-1.0.0-beta.1。

| Example 启动上半部分 | Example 启动下半部分 | Color实时解析测试一 | Color实时解析测试二 |
|---|---|---|---|
| Example 启动页面Color实时解析 | Example 启动页面Color对照方法 | Color实时解析#FF8467颜色对应的其它值 | Color实时解析#F45789颜色对应的其它值 |
以下是操作的视屏,可以参考一下:
一、插件简介与适配目标
颜色配置是前端开发的常见需求:服务端下发的主题色、运营配置的皮肤色、设计师给到的标注值,通常都是 #RRGGBB 或 #RRGGBBAA 形式的字符串,而 Flutter 渲染层需要的是 Color 对象。color_from_hex 提供的 getColorFromHex 函数负责这个解析过程;配套的 Hex 扩展则提供 toHex() 反向输出,以及 isDark() / isLight() / getBrightness() / getLuminance() 等亮度判断方法。例如,接口返回 #FF8800 时可以直接得到背景色,再根据 isDark() 决定图标用深色还是浅色。
这些能力全部在 Dart 层完成:解析使用 int.parse(hex, radix: 16),亮度使用感知亮度公式,不依赖任何系统能力,也不发起任何方法通道调用。因此 Dart 层在 OpenHarmony 上可以原样运行,适配工作的核心是补齐 ohos 平台工程和一个与 Android/iOS 契约一致的 ArkTS 插件类,保证插件注册链路完整。
二、环境准备
环境搭建参考社区文档:Flutter OH 开发环境搭建,完成 Flutter OH SDK 安装、环境变量和 DevEco Studio 配置。
完成后,在宿主机终端执行以下命令,确认当前选中的是支持 OHOS 的 Flutter 工具链,并能发现目标设备:
flutter --version
flutter doctor -v
hdc list targets


工程使用的工具链和 SDK 配置如下:
| 项目 | 版本或配置 | 用途 |
|---|---|---|
| Flutter OHOS SDK | 3.44.9+ohos-0.0.1-canary1 | Flutter 编译与 OHOS 平台工具链 |
| Flutter 分支 | 0.0.3-ohos-1.0.0-beta.1 | flutter doctor 显示的分支名 |
| Dart SDK | 3.12.2 | Dart 语言与包管理环境 |
| HarmonyOS 开发套件 | 26.0.0(API 26) | 开发套件版本及对应的 API 级别 |
compatibleSdkVersion | 5.1.0(18) | 当前工程声明的最低兼容版本 |
| 插件版本 | 0.0.3 | pubspec.yaml 中的包版本 |
| 原生语言 | ArkTS | HarmonyOS 插件实现 |
| 插件产物 | HAR | 被应用 entry 模块依赖 |
2.1 开发套件版本与工程中的 SDK 版本配置
26.0.0(API 26) 和 5.1.0(18) 涉及 HarmonyOS 开发套件版本(API 版本)及其底座 OpenHarmony 的版本号体系。在本文工程中,相关版本的含义与配置方式如下:
26.0.0(API 26)表示本机 DevEco Studio 与 OpenHarmony SDK 为 API 26(flutter doctor显示available api versions has [26:default])。example/ohos/build-profile.json5的 product 中只声明了compatibleSdkVersion,未显式写compileSdkVersion/targetSdkVersion,构建时使用 DevEco Studio 默认的 API 26 SDK。5.1.0(18)是本文工程中compatibleSdkVersion的属性值,声明最低兼容 API 18。
对应的 product 配置为:
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.1.0(18)",
"runtimeOS": "HarmonyOS"
}

这组配置以 API 26 SDK 编译,最低兼容 API 18。本文真机为 OpenHarmony 6.1.1.120(API 24),高于最低兼容门槛。color_from_hex 的核心功能是纯 Dart 实现,不依赖特定系统版本的 API;插件类中的 getPlatformVersion 仅使用 @kit.BasicServicesKit 的 deviceInfo,属于基础服务,无需额外系统版本要求。
三、从源码仓库开始准备适配工程
3.1 将上游源码同步到 AtomGit
适配已有第三方插件时,先从 Pub 包信息或项目 README 确认上游地址、包名、版本和许可证。同步仓库时保留源码、许可证和提交历史,方便后续跟踪上游更新。
在 AtomGit 网页的新建仓库流程中,找到从已有仓库导入的入口,填写上游 Git 地址,选择自己有写权限的组织或个人空间,设置目标仓库名称后执行导入。完成后检查目标分支、pubspec.yaml、LICENSE 和提交历史是否完整,并记录适配起点的提交号。如果上游本身托管在 AtomGit,也可以通过 Fork 获得自己的工作仓库。
本文适配的 color_from_hex 上游托管在 GitHub(DHY-SOLUTIONS/plugin-Color-FromHex),包名 color_from_hex,基线版本 0.0.3,上游仓库 LICENSE 为 GPL-3.0。下面直接使用 GitHub 地址拉取代码;如需同步到 AtomGit 接收仓库,可在导入后再推送适配提交与 TAG。
3.2 将代码拉取到宿主机
在安装了 Flutter OH 和 DevEco Studio 的开发电脑上打开终端,进入准备存放项目的目录,执行:
git clone https://github.com/DHY-SOLUTIONS/plugin-Color-FromHex.git
cd plugin-Color-FromHex
pwd
ls
git remote -v
git status --short --branch
git rev-parse HEAD

git clone 会创建 plugin-Color-FromHex/ 目录;cd 后的位置就是下文所说的插件仓库根目录,这里应能看到 pubspec.yaml、lib/ 和 example/。Git 仓库名是 plugin-Color-FromHex,Dart 包名是 color_from_hex。
需要使用与本文相同的代码版本时,在没有未提交修改的仓库中切换到以下提交:
git switch --detach f0772314efb0b7c7d06a4a0ba7bde51d3ae0cf63
适配其他插件时,使用该插件对应版本的 tag 或 commit 作为分支起点。

图 1:在宿主机终端输入仓库拉取命令。
3.3 在仓库根目录确认分支与 TAG
接着在 plugin-Color-FromHex/ 根目录确认分支。本仓库沿用上游的 master 分支承载适配改动,并按 版本号-ohos-适配版本 的规则打发布 TAG,便于业务按 Flutter 框架版本选择依赖。本例为:
git branch --show-current
git tag 0.0.3-ohos-1.0.0-beta.1
git tag -l
如果团队约定需要隔离适配改动,也可以按 feat/ohos_库名称_版本号 创建分支;两种方式选其一即可,关键是 TAG 或分支名能在依赖表中唯一对应一个适配版本。

图 2:在 plugin-Color-FromHex 仓库根目录确认分支与发布 TAG。
3.4 自动补全 OHOS 适配结构
color_from_hex 仓库已经包含完整的 ohos/ 平台工程,直接运行示例时可以跳过本节;了解结构如何生成,有助于适配其他尚无 ohos/ 目录的插件。
标准的补全方式是在插件根目录执行:
flutter create --template=plugin --platforms=ohos --project-name color_from_hex .
git status --short
git diff -- pubspec.yaml lib example
--template=plugin指定插件模板。--platforms=ohos指定需要补全的平台。--project-name color_from_hex使用 Dart 包名,避免把含连字符和大写字母的仓库目录名作为包名。- 最后的
.表示在当前插件目录补全工程,不是另建一层目录。
本文适配时,本机旧版 Xcode(13.2.1)的 xcodebuild 不支持 -skipPackageUpdates 参数,flutter create 直接崩溃。改用 Flutter OHOS fork 自带的插件模板(templates/app_shared/ 下的 plugin/ohos.tmpl)手工复刻,共 7 个文件:ohos/ 的 index.ets、oh-package.json5、hvigorfile.ts、BuildProfile.ets、build-profile.json5、module.json5 和 ArkTS 插件类。生成或复刻后,通过 diff 检查 pubspec.yaml 的变化,保留已有 API、其他平台注册项及依赖配置。不同 Flutter OH 版本生成的模板可能略有差异。
如果生成后 example/ohos/ 仍不存在,进入已有示例应用补全平台:
cd example
flutter create --platforms=ohos .
cd ..

图 3:在插件根目录输入 OHOS 结构补全命令。
3.5 适配后的项目目录
适配后的关键目录如下:
plugin-Color-FromHex/
├── lib/
│ ├── color_from_hex.dart # 入口导出
│ ├── get_color_from_hex.dart # getColorFromHex 解析函数
│ └── to_hex_color.dart # Hex 扩展(toHex/isDark 等)
├── ohos/
│ ├── index.ets # 插件导出
│ ├── oh-package.json5 # HAR 包信息
│ └── src/main/
│ ├── ets/components/plugin/
│ │ └── ColorFromHexPlugin.ets # ArkTS 插件类
│ └── module.json5 # HAR 模块声明
├── example/
│ ├── lib/main.dart # 示例页面
│ ├── integration_test/ # 真机集成测试
│ └── ohos/entry/ # 宿主 entry 工程
├── test/ # Dart 单元测试
├── docs/ # 适配博客与真机截图
└── pubspec.yaml
项目根目录如下,其中包含 ohos/、example/ohos/,以及 OpenHarmony 中英文说明、变更记录和适配文档:

图 4:适配后的 plugin-Color-FromHex 项目根目录。
| 文件 | 主要职责 |
|---|---|
lib/color_from_hex.dart | 入口,导出解析函数与 Hex 扩展 |
lib/get_color_from_hex.dart | 十六进制字符串到 Color 的解析规则 |
lib/to_hex_color.dart | Color 转十六进制字符串及亮度判断 |
ColorFromHexPlugin.ets | 注册 Flutter 通道,提供模板方法 getPlatformVersion |
插件 module.json5 | 声明 HAR 模块(无权限声明) |
示例 entry module.json5 | 声明宿主应用 Ability、设备类型和权限场景 |
example/lib/main.dart | 演示实时解析、输入格式色板和工具方法卡片 |
四、Dart 接口与通道分析
OHOS 适配需要先分清"哪些逻辑走 Dart、哪些走通道"。color_from_hex 的 lib/ 目录只有三个纯 Dart 文件,没有任何 MethodChannel 调用;唯一的通道出现在原生插件类里,用于承载 flutter create 模板自带的 getPlatformVersion 方法,Dart 层从未调用。适配其他已有平台的插件时,也应保留其公开接口和其他平台实现。
本例的对应关系如下:
| Dart 入口或模型 | 通道协议 | OHOS 实现 | 应保持的行为 |
|---|---|---|---|
getColorFromHex(hexColor, {defaultColor}) | 无(纯 Dart) | 无需原生实现 | 空串返回默认色或抛 ArgumentError;6 位输入补 FF 透明度 |
Color.toHex({leadingHashSign, includeAlpha}) | 无(纯 Dart) | 无需原生实现 | 输出格式与参数一致,组件顺序为 A、R、G、B |
isDark() / isLight() / getBrightness() / getLuminance() | 无(纯 Dart) | 无需原生实现 | 亮度公式与 Flutter 渲染语义一致 |
| 模板方法(仅插件骨架) | color_from_hex / getPlatformVersion | deviceInfo.displayVersion | 与 Android/iOS 模板契约一致,未知方法 notImplemented() |
4.1 跨端架构与调用时序
Flutter 侧和 HarmonyOS 侧之间的分工是:
- 核心功能走纯 Dart:
getColorFromHex和Hex扩展只依赖flutter的Color,在 Dart 虚拟机内同步完成,跨平台共享同一份实现; - 通道仅承载模板契约:ArkTS 插件类注册
MethodChannel('color_from_hex'),实现getPlatformVersion,保证插件注册链路与 Android/iOS 一致,但业务不会用到它。
业务调用 getColorFromHex('#FF8800') 时,结果在 Dart 侧直接返回,不存在异步等待;方法通道只影响插件能否被正确注册。
4.1.1 一次插件方法调用的时序
虽然业务不调用通道,插件注册后的方法分发链路仍然值得核对。以模板方法为例:
4.2 解析规则:lib/get_color_from_hex.dart
getColorFromHex 把任意大小写、带或不带 # 的十六进制字符串统一解析为 Color:
Color getColorFromHex(String hexColor, {Color? defaultColor}) {
if (hexColor.isEmpty) {
if (defaultColor != null) {
return defaultColor;
} else {
throw ArgumentError('Can not parse provided hex $hexColor');
}
}
hexColor = hexColor.toUpperCase().replaceAll('#', '');
if (hexColor.length == 6) {
hexColor = 'FF$hexColor';
}
return Color(int.parse(hexColor, radix: 16));
}
各输入形态的解析结果如下:
| 输入 | 解析过程 | 结果 |
|---|---|---|
'#FF8800' | 去掉 #,6 位补 FF | Color(0xFFFF8800),不透明 |
'ff8800' | 先 toUpperCase() | 与上一行等价,大小写不敏感 |
'FF880080' | 8 位,前两位是 alpha | Color(0xFF880080),半透明 |
'' + defaultColor | 空串直接走兜底 | 返回 defaultColor |
'' 无默认色 | 空串直接抛错 | ArgumentError |
8 位输入的组件顺序是 AARRGGBB:前两位是透明度,不是某些平台习惯的 RRGGBBAA。这是接入时最容易踩的语义差异。
4.3 公开 API 与平台接口
lib/to_hex_color.dart 以扩展方式给 Color 增加能力:
extension Hex on Color {
/// return hex String
String toHex({bool leadingHashSign = true, bool includeAlpha = false}) =>
'${leadingHashSign ? '#' : ''}'
'${includeAlpha ? alpha.toRadixString(16).padLeft(2, '0') : ''}'
'${red.toRadixString(16).padLeft(2, '0')}'
'${green.toRadixString(16).padLeft(2, '0')}'
'${blue.toRadixString(16).padLeft(2, '0')}';
/// Return true if given Color is dark
bool isDark() => getBrightness() < 128.0;
/// Return true if given Color is light
bool isLight() => isDark();
/// Returns Brightness of give Color
double getBrightness() => (red * 299 + green * 587 + blue * 114) / 1000;
/// Returns Luminance of give Color
double getLuminance() => computeLuminance();
}
各方法的语义如下:
toHex():默认输出带#的 6 位小写十六进制;includeAlpha: true时在开头追加 2 位透明度,与解析侧的 AARRGGBB 顺序对应,保证往返一致;isDark()/isLight():以感知亮度 128 为阈值,两个方法互为镜像;getBrightness():(R×299 + G×587 + B×114) / 1000,范围 0.0 ~ 255.0;getLuminance():转发 FlutterColor.computeLuminance(),返回标准相对亮度。
这些方法全部是同步纯函数,接入时不需要初始化,也不需要 await。
4.4 Dart 通道协议分析
4.4.1 通道名称必须两端完全一致
插件类在 ArkTS 侧注册通道:
this.channel = new MethodChannel(binding.getBinaryMessenger(), "color_from_hex");
通道名称属于跨语言协议。Dart 和 ArkTS 任何一端拼写不一致,都会出现"方法未实现"等问题。本库的 Dart 层没有手写通道代码,通道名只在 ArkTS 插件类出现一次,但仍要与 Android(com.dhy.color_from_hex 插件类注册的通道)保持一致。
4.4.2 Dart 层为什么没有通道实现
模板通常生成的 color_from_hex_method_channel.dart、color_from_hex_platform_interface.dart 在本仓库中不存在,lib/ 只导出两个纯 Dart 文件:
export 'get_color_from_hex.dart';
export 'to_hex_color.dart';
这是有意保留的上游形态:核心功能不需要平台通道,删除模板 Dart 文件可以避免暴露从未实现的接口。test/color_from_hex_method_channel_test.dart 中对应的 import 也以注释形式保留。适配其他插件时,如果上游有平台接口文件,则不能照搬本节,应保留平台接口并在 OHOS 上实现。
4.4.3 未实现方法与异常的行为
ArkTS 侧的 onMethodCall 对未知方法返回 notImplemented(),所有分发逻辑包在 try/catch 中:
onMethodCall(call: MethodCall, result: MethodResult): void {
try {
if (call.method == "getPlatformVersion") {
result.success("OpenHarmony " + deviceInfo.displayVersion)
} else {
result.notImplemented()
}
} catch (err) {
result.error("ColorFromHexPluginError", (err as Error).message, null)
}
}
result.error 使用固定错误码 ColorFromHexPluginError,Dart 侧会以 PlatformException 形式收到,不会静默失败。
五、补全 OHOS 原生实现与工程配置
5.1 在 ColorFromHexPlugin.ets 中实现原生能力
color_from_hex 的核心功能在 Dart 层完成,OHOS 原生侧需要补全的是一个与 Android/iOS 契约一致的模板插件类:注册 MethodChannel('color_from_hex')、实现 getPlatformVersion、处理未知方法和异常。这样 Flutter 工具链才能在构建时正确生成注册代码,示例应用也能像 Android/iOS 一样通过 getPlatformVersion 验证插件链路。
ColorFromHexPlugin 实现 FlutterPlugin 和 MethodCallHandler。
原生插件位于:
ohos/src/main/ets/components/plugin/ColorFromHexPlugin.ets
5.1.1 引入 Flutter 和 HarmonyOS 能力
import {
FlutterPlugin,
FlutterPluginBinding,
MethodCall,
MethodCallHandler,
MethodChannel,
MethodResult,
} from '@ohos/flutter_ohos';
import { deviceInfo } from '@kit.BasicServicesKit';
其中:
FlutterPlugin负责接入 Flutter Engine 生命周期;MethodChannel接收 Dart 发来的命令;MethodCallHandler/MethodResult用于方法分发和结果回传;deviceInfo来自@kit.BasicServicesKit,提供displayVersion等设备信息字段。
没有 EventChannel、传感器或系统能力相关的 import——本插件不订阅任何系统事件。
5.1.2 连接 Flutter Engine
private channel: MethodChannel | null = null;
getUniqueClassName(): string {
return "ColorFromHexPlugin"
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "color_from_hex");
this.channel.setMethodCallHandler(this)
}
onAttachedToEngine 在引擎启动、插件注册时被调用:创建通道并设置处理器。getUniqueClassName() 返回值必须与 pubspec.yaml 中的 pluginClass 一致,否则注册器无法加载插件。
5.1.3 处理 MethodChannel 命令
onMethodCall(call: MethodCall, result: MethodResult): void {
try {
if (call.method == "getPlatformVersion") {
result.success("OpenHarmony " + deviceInfo.displayVersion)
} else {
result.notImplemented()
}
} catch (err) {
result.error("ColorFromHexPluginError", (err as Error).message, null)
}
}
方法名和返回值与 Android 模板的 "Android " + Build.VERSION.RELEASE、iOS 模板的 "iOS " + systemVersion 语义对齐。选择 deviceInfo.displayVersion 前,先在 DevEco SDK 的 @ohos.deviceInfo.d.ts 中确认字段名,避免凭记忆写出不存在的属性。
5.1.4 统一错误处理
onMethodCall 外层的 try/catch 把所有异常统一转换成 result.error,错误码为 ColorFromHexPluginError,错误消息取自异常对象。Dart 侧对应收到 PlatformException(code: ColorFromHexPluginError, ...),可以在 catchError 或 try/catch 中处理。
color_from_hex 的通道只承载模板方法,异常场景极少触发;但保留统一的错误出口是平台插件的基本素养,也便于后续在原生侧扩展真实能力时复用。
5.1.5 Engine 解绑时释放资源
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null)
this.channel = null
}
}
Flutter Engine 销毁时移除处理器并释放通道引用。相比持有系统监听的插件,这里没有额外的传感器或事件流资源,但清理逻辑不能省略——它保证插件在热重启、引擎重建等场景下不会重复注册处理器。
5.2 声明插件和宿主权限
color_from_hex 不访问传感器、剪贴板、网络等系统能力,无需任何权限。插件 HAR 与示例宿主都保持最小权限声明,这是纯 Dart 库适配的优势之一。
5.2.1 插件 HAR 的权限
插件的 ohos/src/main/module.json5 保持模板原样,没有 requestPermissions 字段:
{
"module": {
"name": "color_from_hex",
"type": "har",
"deviceTypes": [
"default",
"tablet"
]
}
}
接入方不需要为这个库在 HAR 中追加任何权限声明。
5.2.2 应用 entry 的权限
最终安装的是宿主应用。示例工程的 example/ohos/entry/src/main/module.json5 只声明了 Flutter 调试需要的网络权限:
{
"module": {
"requestPermissions": [
{"name": "ohos.permission.INTERNET"}
]
}
}
INTERNET 是 Flutter OHOS 工具链调试运行(如 DevTools、热重载通道)所需的常规权限,与 color_from_hex 的功能无关。业务接入时,如果宿主应用本身没有网络需求,也可以不声明。
权限声明和运行时授权是两个步骤。接入应用时,还需根据目标 SDK 的权限定义处理授权要求;module.json5 中的声明不会自动完成运行时授权。
5.3 注册并导出插件
pubspec.yaml 通过以下配置声明 OHOS 插件类:
flutter:
plugin:
platforms:
android:
package: com.dhy.color_from_hex
pluginClass: ColorFromHexPlugin
ios:
pluginClass: ColorFromHexPlugin
ohos:
pluginClass: ColorFromHexPlugin
ohos.pluginClass: ColorFromHexPlugin 与 ArkTS 类中的 getUniqueClassName() 返回值完全一致。
插件的 ohos/index.ets 需要导出实现:
import ColorFromHexPlugin from './src/main/ets/components/plugin/ColorFromHexPlugin';
export default ColorFromHexPlugin;
执行 flutter pub get 和构建后,Flutter 工具会为应用生成插件注册代码。本例生成的 example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets 中包含:
flutterEngine.getPlugins()?.add(new ColorFromHexPlugin());
通常不应手工编辑 GeneratedPluginRegistrant.ets,因为下次构建可能覆盖它。
注册异常的排查步骤见第九节 MissingPluginException。
5.4 检查 example 的 OHOS 应用结构
本例的 example/ohos/build-profile.json5 在 products 中设置最低兼容版本。下面是需核对的配置片段,请合并到现有工程;其中 signingConfig: "default" 需要与本机配置的签名名称一致,签名材料保留在本地:
{
"app": {
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.1.0(18)",
"runtimeOS": "HarmonyOS"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": ["default"]
}
]
}
]
}
工程未显式声明 compileSdkVersion / targetSdkVersion,构建时使用本机 DevEco Studio 默认的 API 26 SDK。另外,AppScope/app.json5 的 bundleName 为 com.example.ohos_example_scaffold,必须与签名 Profile 绑定的包名一致。
配置后,在 DevEco Studio 中执行一次 Sync Project。如果 entry 模块正常识别,Project 视图中会出现 entry,并能打开 entry 模块的签名配置。
六、补全交付文件并提交适配分支
6.1 除代码外还要补全哪些文件
代码适配完成后,还需要整理安装说明、接口文档、版本记录和开源信息。接收仓库有专用模板时,按其格式填写:
| 文件 | 应写清楚的内容 |
|---|---|
README.OpenSource | 上游名称、源码地址、适配版本或提交、版权及许可证信息;按仓库模板列出第三方依赖 |
README.md | 原项目说明、OHOS 支持入口、配套 Demo 和文档链接;保留上游信息 |
README.OpenHarmony_CN.md | 简介、Git 安装方式、TAG 版本对应关系、环境约束、权限、接口表、示例、已验证范围和遗留问题 |
README.OpenHarmony.md | 与中文说明对应的英文文档 |
CHANGELOG.OpenHarmony.md | OHOS 新增能力、适配版本、兼容限制与测试范围 |
LICENSE / NOTICE | 保留上游许可证;NOTICE 按许可证和原项目要求保留或补充 |
example/README.md | 依赖方式、运行目录、签名、操作步骤与效果图;覆盖解析与工具方法演示 |
pubspec.yaml、ohos/oh-package.json5 | 核对包名、版本、插件注册、仓库地址、许可证和依赖 |
.gitignore | 忽略构建缓存及本机签名材料,不漏提交必要源码和配置 |
README.OpenSource 记录库本身的来源与版本。本例的包名为 color_from_hex,版本为 0.0.3,上游仓库 LICENSE 为 GPL-3.0。注意本仓库内部存在许可证表述不一致:ohos/oh-package.json5 写的是 Apache-2.0,README.OpenHarmony_CN.md 写的是 MIT,交付前应统一改为与 LICENSE 一致的 GPL-3.0,避免合规歧义。Flutter 和 HarmonyOS SDK 版本写入环境说明。
6.2 提交前检查
提交前先完成第八节的插件、example 和真机测试,再从根目录检查改动:
git branch --show-current
git diff --check
git status --short
git diff --stat
git diff
检查 diff 中的接口、平台注册和依赖变化,移除本机路径及签名信息,并使文档中的版本和分支与提交内容一致。
6.3 提交并推送到远程仓库
文档和代码整理完成后,在根目录暂存并提交。文件名按项目实际情况调整:
git add ohos pubspec.yaml example test .gitignore .metadata
git add README.md README.OpenHarmony_CN.md
git add README.OpenHarmony.md CHANGELOG.OpenHarmony.md docs
git diff --cached --check
git diff --cached --stat
git diff --cached
git commit -m "feat: adapt color_from_hex to OpenHarmony"
git remote -v
git branch --show-current
git push origin master
git tag 0.0.3-ohos-1.0.0-beta.1
git push origin 0.0.3-ohos-1.0.0-beta.1
本仓库直接在 master 分支承载适配提交,并用 TAG 0.0.3-ohos-1.0.0-beta.1 标记发布点,README 中的依赖表按 Flutter 框架版本(3.44)指向该 TAG。若团队约定使用适配分支,把 master 替换为 feat/ohos_color_from_hex_0.0.3 即可。
DevEco 可能向 example/ohos/build-profile.json5 写入本机签名配置,需要在提交前从暂存内容中移除。推送后在托管平台发起合并请求,说明上游来源和版本、OHOS 实现范围、依赖及权限、测试环境、操作结果、已知限制,并附 Demo 运行图。目标分支和评审流程以接收仓库要求为准。
七、使用根目录 example 演示接入
仓库自带 example/,可以直接用来调试插件和体验颜色解析效果。
7.1 本地适配时使用路径依赖
当前 example/pubspec.yaml 的依赖是:
dependencies:
flutter:
sdk: flutter
color_from_hex:
path: ../
../ 相对于 example/pubspec.yaml 指向插件根目录,修改根目录插件后可直接联调。
7.2 通过 AtomGit 引入插件
业务应用引入时,将 color_from_hex 的 path 配置替换为下面的 Git 依赖。这里固定到本文使用的 TAG:
dependencies:
flutter:
sdk: flutter
color_from_hex:
git:
url: https://github.com/DHY-SOLUTIONS/plugin-Color-FromHex.git
ref: 0.0.3-ohos-1.0.0-beta.1
使用自己的适配版本时,先推送提交,再将 url 改为对应仓库,ref 改为适配分支名或 TAG。正式发布后可固定到 tag 或 commit。
从插件根目录执行:
cd example
flutter pub get
flutter pub deps
检查 example/pubspec.lock 中 color_from_hex 的来源为 git,并核对 url、ref 和 resolved-ref。同时检查没有 dependency_overrides 或 pubspec_overrides.yaml 将其覆盖回本地依赖,确认应用使用的是 Git 依赖。
7.3 调用接口实现颜色解析
下面的页面展示 hex 输入、实时解析和亮度判断,可用于 example/lib/main.dart。仓库中的完整 Demo 还提供输入格式色板和工具方法卡片。
import 'package:flutter/material.dart';
import 'package:color_from_hex/color_from_hex.dart';
void main() {
runApp(const MaterialApp(home: HexColorPage()));
}
class HexColorPage extends StatefulWidget {
const HexColorPage({super.key});
State<HexColorPage> createState() => _HexColorPageState();
}
class _HexColorPageState extends State<HexColorPage> {
final TextEditingController _controller =
TextEditingController(text: '#FF8800');
Color? _parsed;
String? _error;
void _parse(String input) {
setState(() {
try {
_parsed = getColorFromHex(input);
_error = null;
} catch (e) {
_parsed = null;
_error = '$e';
}
});
}
void dispose() {
_controller.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('color_from_hex Demo')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _controller,
onChanged: _parse,
decoration: const InputDecoration(
labelText: '输入 hex 颜色',
hintText: '如 #FF8800 / FF8800 / #FF880080',
),
),
const SizedBox(height: 16),
if (_error != null)
Text(_error!, style: const TextStyle(color: Colors.redAccent))
else ...[
Container(
width: 64,
height: 64,
color: _parsed,
),
const SizedBox(height: 8),
Text('Color(${_parsed.toARGB32()})'),
Text('toHex(): ${_parsed!.toHex()}'),
Text('toHex(includeAlpha): ${_parsed!.toHex(includeAlpha: true)}'),
Text('isDark: ${_parsed!.isDark()}'),
],
],
),
),
);
}
}
7.4 页面退出时的资源处理
异步回调先检查 mounted,避免页面销毁后继续调用 setState。color_from_hex 的 API 都是同步纯函数,没有订阅或原生资源需要清理,dispose 中只需释放页面自己的 TextEditingController 后调用 super.dispose()。
如果应用中存在全局主题色解析(例如启动时从服务端配置解析主题),可以在应用级做一次解析并缓存结果,避免在 build 中反复调用字符串解析。
八、验证、构建与鸿蒙设备运行效果
8.1 分别验证插件与 example
从插件仓库根目录执行:
flutter pub get
flutter analyze
flutter test
cd example
flutter pub get
flutter analyze
flutter test
test/ 下的模板测试文件为空壳(void main() {}),功能验证主要依靠 example/integration_test/plugin_integration_test.dart:断言示例页渲染、"支持的输入格式"区块存在,以及输入 #FF0000 后实时解析输出 toHex(): #ff0000 与 往返一致: true 等。集成测试需在真机或模拟器上执行:
cd example
flutter test integration_test
Dart 测试覆盖接口和页面逻辑。color_from_hex 的功能不依赖传感器、权限等设备能力,无需额外的真机能力验证。
8.2 确认设备连接
hdc list targets
flutter devices
设备首次连接电脑时,需要在手机端确认调试授权。列表为空时,检查 USB 连接、调试模式和电脑授权。
8.3 配置签名
真机安装的 HAP 通常需要有效签名。推荐使用 DevEco Studio 为 entry 模块配置自动签名:
- 用 DevEco Studio 打开
example/ohos,不是仓库根目录; - 等待工程 Sync 成功,确认 Project 视图中存在
entry模块; - 打开 File > Project Structure > Signing Configs;
- 为
defaultproduct 选择或生成签名; - 确认设备、应用包名、证书和 Profile 匹配;
- 再回到终端执行 Flutter 构建或运行。
签名材料保存在本机,公开仓库中只保留构建所需的通用配置。
8.4 运行示例
以下命令在 example/ 目录执行,将 <device-id> 替换为设备列表中的实际 ID:
flutter run -d <device-id>
也可以先构建 HAP:
flutter build hap --debug
典型产物位于:
example/ohos/entry/build/default/outputs/default/
目录中通常包含已签名和未签名 HAP。真机安装应选择与当前设备匹配的已签名产物。
8.5 在设备上测试颜色解析与工具方法
- 打开应用,确认实时解析面板已展示
#FF8800的默认解析结果; - 在输入框分别输入
FF0000(无#)、#00FF0080(带透明度)、#ffa500(小写),对照"支持的输入格式"色板卡片确认解析结果一致; - 清空输入框,观察错误提示(
ArgumentError信息); - 打开"空输入时使用默认色(灰色)兜底"开关,再次清空输入,确认返回灰色而不是报错;
- 在"Color 工具方法"区域核对
toHex()、isDark、亮度与相对亮度展示; - 退出页面再进入,确认状态正常恢复,无崩溃。
8.6 鸿蒙设备运行效果
完成适配后,示例应用可以在 OpenHarmony 设备上完成十六进制颜色解析、反向输出和亮度判断,全部能力与 Android/iOS 共享同一份 Dart 实现。
真机运行效果如下:
| Example 启动上半部分 | Example 启动下半部分 | Color实时解析测试一 | Color实时解析测试二 |
|---|---|---|---|
| Example 启动页面Color实时解析 | Example 启动页面Color对照方法 | Color实时解析#FF8467颜色对应的其它值 | Color实时解析#F45789颜色对应的其它值 |
以下是操作的视屏,可以参考一下:
color_from_hex 不依赖设备硬件和系统服务,满足最低 API 要求的设备行为一致;截图基于 OpenHarmony 6.1.1.120(API 24)真机。
九、FAQ:适配过程与使用问题
9.1 Missing SDK components
典型错误如下:
Missing SDK components. SDK path: ...,
missing components: toolchains,ets,js,native,previewer.
这个错误发生在 Hvigor 同步阶段。通常需要检查构建工具使用的 SDK 路径、组件是否完整,以及 Hvigor 与 SDK 的版本是否匹配。
处理顺序:
- 在 DevEco Studio SDK Manager 中确认 API 26 组件已经下载完整;
- 检查 Flutter 和 DevEco Studio 使用的 SDK 路径是否一致;
- 避免误用
/Applications/DevEco-Studio.app/Contents/sdk之类的不完整目录; - 确认 SDK 根目录下存在
toolchains、ets、js、native、previewer; - 执行
flutter config --ohos-sdk <正确路径>; - 重新执行
flutter doctor -v和 DevEco Studio Sync。
因为 Sync 和 Compile 首先读取 Mac 本地 SDK。手机 API 版本只在部署、安装和运行时参与兼容判断。即使完全不连接手机,本地 SDK 不完整时也会得到相同错误。
当前工程的 compatibleSdkVersion 是 API 18,因此 API 24 在安装版本门槛上是满足的;color_from_hex 的核心功能为纯 Dart 实现,不依赖系统版本能力,安装后即可使用。
9.2 DevEco Studio 中看不到 entry 模块
插件的 ohos/ 目录是 HAR 模块,可安装应用的 entry 模块位于 example/ohos/entry。
请直接使用 DevEco Studio 打开:
plugin-Color-FromHex/example/ohos
如果仍看不到 entry,先解决 SDK Sync 错误,再检查 example/ohos/build-profile.json5 的 modules 是否包含 ./entry。同步失败时,Project Structure 无法正确解析模块,签名界面也可能不显示 entry。
9.3 无法手动签名
签名配置依附于可构建的应用模块和 product。只有 HAR 插件模块、工程 Sync 失败,或者打开了错误目录时,DevEco Studio 都可能无法提供 entry 签名入口。
建议先确认:
- 打开的是
example/ohos; - SDK 组件完整并且 Sync 成功;
entry的模块类型为entry;defaultproduct 和 target 已正确关联;- 当前账号、证书和调试设备状态有效。
9.4 解析结果不符合预期或页面无颜色
按以下顺序检查:
- 输入是否符合
#RRGGBB/#RRGGBBAA格式,#可以省略,大小写不敏感; - 8 位输入的顺序是否正确——前两位是透明度(AARRGGBB),不是 RRGGBBAA;
- 空输入且未提供
defaultColor时会抛出ArgumentError,这是预期行为,检查界面是否把错误当成了无结果; - 输入变化后是否调用了
setState,onChanged中漏掉状态更新会导致色块不刷新; - 热重载后确认运行的是最新代码,必要时热重启。
9.5 MissingPluginException
这通常表示 Dart 通道找不到已注册的原生插件。新增原生插件后需要重新构建应用。从仓库根目录执行:
cd example
flutter clean
flutter pub get
flutter run -d <device-id>
如果仍然出现,检查自动生成的插件注册文件中是否包含 ColorFromHexPlugin,同时核对 pubspec.yaml、ohos/index.ets 和 oh-package.json5。
9.6 在 build 中反复解析是否合适
getColorFromHex 是同步纯函数,重复调用本身没有副作用,但在 build 方法里对同一字符串反复解析没有必要。推荐做法:
- 在
initState或输入回调中解析一次,把结果保存在状态变量里; - 全局主题色在应用启动时解析一次并缓存;
- 多个页面共用同一配置色时,由应用级服务统一解析后分发。
9.7 编译成功但安装失败
常见原因包括:
- HAP 未签名或使用了错误的 Profile;
- 设备未加入调试设备列表;
- 包名与签名 Profile 不匹配;
- 安装包的
compatibleSdkVersion高于设备 API; - 手机上已经安装了使用不同证书签名的同包名应用。
根据安装错误码区分签名、版本和包名冲突,再处理对应配置。
9.8 flutter create 不认识 ohos,或包名不合法
先执行 flutter --version,确认使用的是 OHOS 版工具链,环境配置回到第二节的社区链接核对。包名报错时,确认当前目录包含目标插件的 pubspec.yaml,并显式传入 --project-name color_from_hex;仓库名 plugin-Color-FromHex 含大写字母和连字符,不能直接作为 Dart 包名。本仓库适配时 flutter create 因旧版 Xcode 崩溃,改为手工复刻 fork 自带模板,见 3.4 节。
9.9 Git 依赖提示找不到 TAG 或无权限
先检查 URL 是否指向正确的仓库(本文为 GitHub 上的 plugin-Color-FromHex),再确认 0.0.3-ohos-1.0.0-beta.1 TAG 已推送——TAG 与分支是独立推送的,git push origin master 不会带上 TAG,需要单独执行 git push origin 0.0.3-ohos-1.0.0-beta.1。也可以先用适配提交号 8fb8bd663b74ac34527f082c0558fab7a885fa02 作为 ref。私有仓库还需在本机配置 Git 认证。
9.10 改了本地 ArkTS,Demo 为什么没变化
先检查 example/pubspec.yaml:Git 依赖读取远程提交,不会自动读取本地插件改动。本地联调切回 path: ../;测试远程版本则先提交推送,再更新依赖并核对 pubspec.lock 的 resolved-ref。原生代码变动后停止应用并重新构建运行,不能只做 Dart 热重载。
9.11 8 位颜色解析后透明度不符合预期
检查输入顺序:getColorFromHex 按 AARRGGBB 解析,前两位是 alpha。把 RRGGBBAA 顺序的字符串传入(例如本意是 R=FF、G=88、B=00、A=80 的 FF880080)会得到另一种颜色。解析结果可用 toHex(includeAlpha: true) 回显核对,其输出顺序与解析规则一致;需要 RRGGBBAA 顺序时,先手动调换前两位再传入。
相关链接
更多推荐




所有评论(0)