Flutter三方库适配OpenHarmony【flutter_libphonenumber】——鸿蒙平台插件包的创建与注册
欢迎来到Flutter三方库适配OpenHarmony系列文章!本系列围绕这个电话号码处理库的鸿蒙平台适配,进行全面深入的技术分享。欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net上一篇我们解析了联合插件的架构设计。本篇将手把手讲解鸿蒙平台插件包的完整创建过程,包括目录结构、配置、ohos/原生目录的组织方式、注册机制,以及的自动生成原
前言
欢迎来到 Flutter三方库适配OpenHarmony 系列文章!本系列围绕 flutter_libphonenumber 这个 电话号码处理库 的鸿蒙平台适配,进行全面深入的技术分享。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net


上一篇我们解析了联合插件的架构设计。本篇将 手把手 讲解鸿蒙平台插件包 flutter_libphonenumber_ohos 的完整创建过程,包括目录结构、pubspec.yaml 配置、ohos/ 原生目录的组织方式、dartPluginClass 注册机制,以及 GeneratedPluginRegistrant 的自动生成原理。
掌握了插件包的创建与注册流程,你就能为任何 Flutter 三方库创建鸿蒙平台实现包。这是鸿蒙适配的 实操核心。
一、插件包的完整目录结构
1.1 顶层目录
flutter_libphonenumber_ohos 插件包的完整目录结构如下:
flutter_libphonenumber_ohos/
├── lib/
│ └── flutter_libphonenumber_ohos.dart # Dart 侧实现
├── ohos/
│ ├── src/main/
│ │ ├── ets/components/plugin/
│ │ │ ├── FlutterLibphonenumberPlugin.ets # ArkTS 插件入口
│ │ │ └── PhoneNumberUtil.ets # ArkTS 核心工具类
│ │ └── module.json5 # 模块配置
│ ├── oh-package.json5 # 鸿蒙包配置
│ ├── build-profile.json5 # 构建配置
│ ├── hvigorfile.ts # 构建脚本
│ ├── index.ets # 包入口文件
│ └── BuildProfile.ets # 构建变量
├── example/ # 演示工程
│ ├── lib/main.dart
│ └── ohos/ # 鸿蒙原生工程
├── pubspec.yaml # Flutter 包配置
└── pubspec_overrides.yaml # 本地依赖覆盖
1.2 目录职责划分
| 目录/文件 | 层级 | 职责 |
|---|---|---|
lib/ |
Dart 侧 | 包含 Dart 平台实现类,通过 MethodChannel 与原生侧通信 |
ohos/ |
原生侧 | 包含 ArkTS 原生代码和鸿蒙工程配置 |
ohos/src/main/ets/ |
原生侧 | ArkTS 源代码目录 |
ohos/oh-package.json5 |
原生侧 | 鸿蒙包的元数据和依赖声明 |
ohos/module.json5 |
原生侧 | 模块类型和设备类型声明 |
ohos/index.ets |
原生侧 | 包的入口文件,导出插件类 |
example/ |
演示 | 完整的演示工程,用于测试和展示 |
pubspec.yaml |
配置 | Flutter 包的核心配置文件 |
关键区别:与 Android 插件的
android/目录和 iOS 插件的ios/目录类似,鸿蒙插件使用ohos/目录存放原生代码。但鸿蒙使用的是 ArkTS 语言和 HAR(Harmony Archive)模块类型。
二、pubspec.yaml 核心配置
2.1 完整配置文件
pubspec.yaml 是 Flutter 包的核心配置文件,它告诉 Flutter 框架如何识别和加载这个插件:
name: flutter_libphonenumber_ohos
description: OpenHarmony implementation of the flutter_libphonenumber plugin.
repository: https://github.com/bottlepay/flutter_libphonenumber/tree/main/packages/flutter_libphonenumber_ohos
issue_tracker: https://github.com/bottlepay/flutter_libphonenumber/issues
version: 1.0.0
environment:
sdk: ">=2.19.0 <4.0.0"
flutter: ">=3.0.0"
flutter:
plugin:
implements: flutter_libphonenumber
platforms:
ohos:
package: com.bottlepay.flutter_libphonenumber
pluginClass: FlutterLibphonenumberPlugin
dartPluginClass: FlutterLibphonenumberOhos
dependencies:
flutter:
sdk: flutter
flutter_libphonenumber_platform_interface: ^2.1.0
dev_dependencies:
flutter_test:
sdk: flutter
plugin_platform_interface: ^2.0.2
2.2 flutter.plugin 配置详解
flutter.plugin 节点是插件注册的核心,每个字段都有特定含义:
flutter:
plugin:
implements: flutter_libphonenumber # ① 声明实现的插件
platforms:
ohos: # ② 目标平台
package: com.bottlepay.flutter_libphonenumber # ③ 原生包名
pluginClass: FlutterLibphonenumberPlugin # ④ ArkTS 入口类
dartPluginClass: FlutterLibphonenumberOhos # ⑤ Dart 入口类
各字段详细说明:
| 字段 | 值 | 说明 |
|---|---|---|
implements |
flutter_libphonenumber |
声明本包是哪个插件的平台实现 |
platforms.ohos |
- | 声明支持 OpenHarmony 平台 |
package |
com.bottlepay.flutter_libphonenumber |
原生侧的包标识符 |
pluginClass |
FlutterLibphonenumberPlugin |
ArkTS 侧的插件入口类名 |
dartPluginClass |
FlutterLibphonenumberOhos |
Dart 侧的平台实现类名 |
2.3 implements 的作用
implements 字段建立了 平台包 与 主包 之间的关联:
flutter_libphonenumber_ohos
│
│ implements: flutter_libphonenumber
│
▼
flutter_libphonenumber(主包)
│
│ 依赖
│
▼
flutter_libphonenumber_platform_interface(接口包)
当 Flutter 框架在鸿蒙平台上运行时,它会:
- 扫描所有依赖包的
pubspec.yaml - 找到
implements: flutter_libphonenumber且platforms包含ohos的包 - 自动使用该包作为
flutter_libphonenumber的鸿蒙平台实现
endorsed 机制:如果主包的
pubspec.yaml中将鸿蒙包列为依赖,则称为 endorsed(背书)。被背书的平台包会自动被引入,开发者无需手动添加依赖。
2.4 dependencies 依赖关系
dependencies:
flutter:
sdk: flutter
flutter_libphonenumber_platform_interface: ^2.1.0
鸿蒙平台包只依赖两个东西:
- flutter SDK — Flutter 框架本身
- platform_interface — 平台接口包,提供抽象基类和数据模型
注意:平台包 不依赖主包(
flutter_libphonenumber),只依赖接口包。这是联合插件架构的关键设计——平台包和主包之间没有直接依赖关系。
三、ohos/ 原生目录详解
3.1 oh-package.json5 — 鸿蒙包配置
oh-package.json5 是鸿蒙原生包的元数据文件,类似于 Node.js 的 package.json:
{
"name": "flutter_libphonenumber_ohos",
"version": "1.0.0",
"description": "OpenHarmony implementation of flutter_libphonenumber",
"main": "index.ets",
"author": "",
"license": "MIT",
"dependencies": {
"@ohos/flutter_ohos": "*"
},
"devDependencies": {},
"peerDependencies": {
"@ohos/flutter_ohos": "*"
}
}
关键字段说明:
| 字段 | 值 | 说明 |
|---|---|---|
name |
flutter_libphonenumber_ohos |
包名,与 pubspec.yaml 中的 name 一致 |
main |
index.ets |
包的入口文件 |
dependencies |
@ohos/flutter_ohos: * |
依赖 Flutter-OHOS 框架 |
peerDependencies |
@ohos/flutter_ohos: * |
声明为 peer 依赖,避免版本冲突 |
3.2 index.ets — 包入口文件
index.ets 是 oh-package.json5 中 main 字段指向的入口文件,它的职责是 导出插件类:
import FlutterLibphonenumberPlugin
from './src/main/ets/components/plugin/FlutterLibphonenumberPlugin';
export default FlutterLibphonenumberPlugin;
这个文件只有两行代码,但它是整个原生侧的 入口点。当 GeneratedPluginRegistrant 通过 import FlutterLibphonenumberPlugin from 'flutter_libphonenumber_ohos' 导入时,实际上就是通过这个 index.ets 找到插件类的。
3.3 module.json5 — 模块配置
{
"module": {
"name": "flutter_libphonenumber_ohos",
"type": "har",
"deviceTypes": [
"default",
"tablet"
]
}
}
| 字段 | 值 | 说明 |
|---|---|---|
name |
flutter_libphonenumber_ohos |
模块名称 |
type |
har |
模块类型为 HAR(Harmony Archive),即库模块 |
deviceTypes |
["default", "tablet"] |
支持的设备类型 |
HAR vs HAP:
har是库模块(类似 Android 的 AAR),用于被其他模块引用;hap是应用模块(类似 Android 的 APK),可以独立安装运行。插件包使用har类型。
3.4 build-profile.json5 — 构建配置
{
"apiType": "stageMode",
"buildOption": {
"arkOptions": {
"runtimeOnly": {
"sources": []
}
}
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": []
}
}
}
}
],
"targets": [
{
"name": "default"
}
]
}
关键配置:
apiType: "stageMode"— 使用 Stage 模型(鸿蒙推荐的应用模型)obfuscation.enable: false— 关闭代码混淆(开发阶段方便调试)targets— 构建目标,默认只有一个default
3.5 hvigorfile.ts — 构建脚本
export { harTasks } from '@ohos/hvigor-ohos-plugin';
这是鸿蒙的构建脚本文件,导出 harTasks 表示使用 HAR 模块的标准构建任务。类似于 Android 的 build.gradle 中的 apply plugin: 'com.android.library'。
3.6 BuildProfile.ets — 构建变量
export const HAR_VERSION = '1.0.0';
export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;
export const TARGET_NAME = 'default';
export default class BuildProfile {
static readonly HAR_VERSION = HAR_VERSION;
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
static readonly DEBUG = DEBUG;
static readonly TARGET_NAME = TARGET_NAME;
}
这个文件提供了构建时的变量,可以在代码中通过
BuildProfile.DEBUG判断当前是否为调试模式。
四、Dart 侧实现文件
4.1 flutter_libphonenumber_ohos.dart
Dart 侧只有一个文件,它的职责是:
- 定义
FlutterLibphonenumberOhos类,继承FlutterLibphonenumberPlatform - 提供
registerWith()静态方法用于自动注册 - 通过
MethodChannel实现 4 个抽象方法
import 'package:flutter/services.dart';
import 'package:flutter_libphonenumber_platform_interface/flutter_libphonenumber_platform_interface.dart';
// MethodChannel 通道名称,必须与 ArkTS 侧一致
const _channel = MethodChannel('com.bottlepay/flutter_libphonenumber_ohos');
class FlutterLibphonenumberOhos extends FlutterLibphonenumberPlatform {
/// 注册为默认平台实现(Flutter 框架自动调用)
static void registerWith() {
FlutterLibphonenumberPlatform.instance = FlutterLibphonenumberOhos();
}
Future<Map<String, String>> format(String phone, String region) async {
return await _channel.invokeMapMethod<String, String>('format', {
'phone': phone, 'region': region,
}) ?? <String, String>{};
}
Future<Map<String, CountryWithPhoneCode>> getAllSupportedRegions() async {
final result = await _channel
.invokeMapMethod<String, dynamic>('get_all_supported_regions') ?? {};
final returnMap = <String, CountryWithPhoneCode>{};
result.forEach((k, v) => returnMap[k] = CountryWithPhoneCode(
countryName: v['countryName'] ?? '',
phoneCode: v['phoneCode'] ?? '',
countryCode: k,
// ... 其他 8 个字段
));
return returnMap;
}
Future<Map<String, dynamic>> parse(String phone, {String? region}) async {
return await _channel.invokeMapMethod<String, dynamic>('parse', {
'phone': phone, 'region': region,
}) ?? <String, dynamic>{};
}
Future<void> init({
Map<String, CountryWithPhoneCode> overrides = const {},
}) async {
return CountryManager().loadCountries(
phoneCodesMap: await getAllSupportedRegions(),
overrides: overrides,
);
}
}
4.2 MethodChannel 通道名称的约定
const _channel = MethodChannel('com.bottlepay/flutter_libphonenumber_ohos');
通道名称必须满足以下要求:
- 全局唯一 — 不能与其他插件的通道名称冲突
- Dart 侧与 ArkTS 侧一致 — 两端使用完全相同的字符串
- 命名规范 — 通常使用
com.公司名/插件名的格式
| 端 | 通道名称定义位置 |
|---|---|
| Dart 侧 | flutter_libphonenumber_ohos.dart 中的 _channel 常量 |
| ArkTS 侧 | FlutterLibphonenumberPlugin.ets 中的 CHANNEL_NAME 常量 |
// ArkTS 侧 — 必须与 Dart 侧完全一致
const CHANNEL_NAME: string = 'com.bottlepay/flutter_libphonenumber_ohos';
五、ArkTS 侧插件入口类
5.1 FlutterLibphonenumberPlugin.ets 完整结构
ArkTS 侧的插件入口类实现了两个接口:FlutterPlugin 和 MethodCallHandler:
import {
FlutterPlugin,
FlutterPluginBinding,
MethodCall,
MethodCallHandler,
MethodChannel,
MethodResult
} from '@ohos/flutter_ohos';
import { PhoneNumberUtil, RegionInfo, PhoneNumber } from './PhoneNumberUtil';
const TAG: string = 'FlutterLibphonenumberPlugin';
const CHANNEL_NAME: string = 'com.bottlepay/flutter_libphonenumber_ohos';
export default class FlutterLibphonenumberPlugin
implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
private phoneUtil: PhoneNumberUtil = PhoneNumberUtil.getInstance();
getUniqueClassName(): string {
return TAG;
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(
binding.getBinaryMessenger(), CHANNEL_NAME
);
this.channel.setMethodCallHandler(this);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel !== null) {
this.channel.setMethodCallHandler(null);
this.channel = null;
}
}
onMethodCall(call: MethodCall, result: MethodResult): void {
if (call.method === 'format') {
this.handleFormat(call, result);
} else if (call.method === 'parse') {
this.handleParse(call, result);
} else if (call.method === 'get_all_supported_regions') {
this.handleGetAllSupportedRegions(result);
} else {
result.notImplemented();
}
}
}
5.2 FlutterPlugin 接口
FlutterPlugin 接口定义了插件的 生命周期方法:
| 方法 | 调用时机 | 职责 |
|---|---|---|
getUniqueClassName() |
注册时 | 返回唯一标识符,用于插件去重 |
onAttachedToEngine() |
引擎绑定时 | 创建 MethodChannel,设置消息处理器 |
onDetachedFromEngine() |
引擎解绑时 | 清理 MethodChannel,释放资源 |
5.3 MethodCallHandler 接口
MethodCallHandler 接口只有一个方法 onMethodCall,负责接收和分发 Dart 侧的调用:
onMethodCall(call: MethodCall, result: MethodResult): void {
// call.method — 方法名(如 'format'、'parse')
// call.argument('key') — 获取参数
// result.success(data) — 返回成功结果
// result.error(code, msg, detail) — 返回错误
// result.notImplemented() — 方法未实现
}
5.4 三个方法的分发
插件入口类支持三个 MethodChannel 方法:
| 方法名 | 处理函数 | 功能 |
|---|---|---|
format |
handleFormat() |
格式化电话号码 |
parse |
handleParse() |
解析电话号码 |
get_all_supported_regions |
handleGetAllSupportedRegions() |
获取所有支持的国家/地区 |
设计原则:插件入口类只负责 消息分发,具体的业务逻辑委托给
PhoneNumberUtil工具类。这种分离使得代码职责清晰,便于维护。
六、dartPluginClass 自动注册机制
6.1 注册流程概述
Flutter 框架通过 dartPluginClass 实现了 零配置 的平台注册。整个流程无需开发者手动干预:
- Flutter 构建工具扫描所有依赖包的
pubspec.yaml - 找到声明了
dartPluginClass的包 - 在编译时自动生成注册代码
- 应用启动时自动调用
registerWith()方法
6.2 registerWith() 的实现
class FlutterLibphonenumberOhos extends FlutterLibphonenumberPlatform {
static void registerWith() {
FlutterLibphonenumberPlatform.instance = FlutterLibphonenumberOhos();
}
}
这个方法做了三件事:
- 创建实例 —
FlutterLibphonenumberOhos()调用构造函数 - Token 验证 —
instancesetter 内部调用PlatformInterface.verifyToken() - 替换默认实现 — 将
_instance从MethodChannelFlutterLibphonenumber替换为鸿蒙实现
6.3 注册前后的实例变化
注册前:
FlutterLibphonenumberPlatform.instance
→ MethodChannelFlutterLibphonenumber(默认实现)
→ 通道名:com.bottlepay/flutter_libphonenumber
注册后:
FlutterLibphonenumberPlatform.instance
→ FlutterLibphonenumberOhos(鸿蒙实现)
→ 通道名:com.bottlepay/flutter_libphonenumber_ohos
关键:注册后,所有通过
FlutterLibphonenumberPlatform.instance发起的调用都会路由到鸿蒙实现,使用鸿蒙专属的 MethodChannel 通道。
七、GeneratedPluginRegistrant 自动生成
7.1 ArkTS 侧的自动注册
Flutter-OHOS 构建工具会在 example 工程中自动生成 GeneratedPluginRegistrant.ets:
import { FlutterEngine, Log } from '@ohos/flutter_ohos';
import FlutterLibphonenumberPlugin from 'flutter_libphonenumber_ohos';
const TAG = "GeneratedPluginRegistrant";
export class GeneratedPluginRegistrant {
static registerWith(flutterEngine: FlutterEngine) {
try {
flutterEngine.getPlugins()?.add(
new FlutterLibphonenumberPlugin()
);
} catch (e) {
Log.e(TAG,
"Tried to register plugins with FlutterEngine ("
+ flutterEngine + ") failed.");
Log.e(TAG, "Received exception while registering", e);
}
}
}
7.2 自动生成的触发条件
| 条件 | 说明 |
|---|---|
pubspec.yaml 中声明了 pluginClass |
告诉构建工具 ArkTS 侧有插件类需要注册 |
| 依赖链中包含该插件包 | example 工程直接或间接依赖了插件包 |
运行 flutter pub get |
触发依赖解析和代码生成 |
7.3 注册链路完整时序
应用启动
│
├── ArkTS 侧注册(原生侧)
│ ├── 1. FlutterEngine 创建
│ ├── 2. GeneratedPluginRegistrant.registerWith(engine)
│ ├── 3. new FlutterLibphonenumberPlugin()
│ ├── 4. engine.getPlugins().add(plugin)
│ ├── 5. plugin.onAttachedToEngine(binding)
│ └── 6. MethodChannel 创建,setMethodCallHandler(this)
│
├── Dart 侧注册(框架侧)
│ ├── 7. Flutter 框架扫描 dartPluginClass
│ ├── 8. 调用 FlutterLibphonenumberOhos.registerWith()
│ └── 9. FlutterLibphonenumberPlatform.instance = 鸿蒙实例
│
└── 注册完成
├── Dart 侧:instance 指向 FlutterLibphonenumberOhos
└── ArkTS 侧:MethodChannel 已就绪,等待消息
双端注册:鸿蒙插件需要在 两端 分别注册——ArkTS 侧注册插件到 FlutterEngine(处理原生消息),Dart 侧注册平台实例(路由 API 调用)。两端通过 MethodChannel 通道名称关联。
八、与 Android/iOS 插件创建的对比
8.1 目录结构对比
| 对比项 | Android | iOS | 鸿蒙(OHOS) |
|---|---|---|---|
| 原生目录 | android/ |
ios/ |
ohos/ |
| 源码目录 | src/main/kotlin/ |
Classes/ |
src/main/ets/ |
| 包配置 | build.gradle |
.podspec |
oh-package.json5 |
| 模块配置 | AndroidManifest.xml |
Info.plist |
module.json5 |
| 构建脚本 | build.gradle |
Podfile |
hvigorfile.ts |
| 入口文件 | 无(Gradle 自动扫描) | 无(podspec 指定) | index.ets |
| 实现语言 | Kotlin/Java | Swift/ObjC | ArkTS |
8.2 插件接口对比
// Android (Kotlin)
class FlutterLibphonenumberPlugin : FlutterPlugin, MethodCallHandler {
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { }
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { }
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { }
}
// iOS (Swift)
public class SwiftFlutterLibphonenumberIosPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) { }
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { }
}
// OHOS (ArkTS)
export default class FlutterLibphonenumberPlugin
implements FlutterPlugin, MethodCallHandler {
onAttachedToEngine(binding: FlutterPluginBinding): void { }
onMethodCall(call: MethodCall, result: MethodResult): void { }
onDetachedFromEngine(binding: FlutterPluginBinding): void { }
}
8.3 关键差异总结
| 特性 | Android | iOS | OHOS |
|---|---|---|---|
| 插件注册方式 | GeneratedPluginRegistrant.java |
GeneratedPluginRegistrant.m |
GeneratedPluginRegistrant.ets |
| 构建系统 | Gradle | CocoaPods | Hvigor |
| 模块类型 | AAR | Framework | HAR |
| 依赖管理 | Maven/Gradle | CocoaPods/SPM | OHPM |
| 最低 API | minSdkVersion | iOS Deployment Target | compatibleSdkVersion |
九、example 工程的鸿蒙配置
9.1 example/ohos/ 目录结构
演示工程的鸿蒙原生部分位于 example/ohos/ 目录:
example/ohos/
├── AppScope/
│ └── app.json5 # 应用级配置
├── entry/
│ ├── src/main/ets/
│ │ ├── entryability/ # 应用入口
│ │ └── plugins/
│ │ └── GeneratedPluginRegistrant.ets # 自动生成
│ ├── oh-package.json5 # entry 模块配置
│ └── build-profile.json5 # entry 构建配置
├── oh-package.json5 # 工程级配置
├── build-profile.json5 # 工程级构建配置
├── hvigorfile.ts # 工程级构建脚本
└── hvigor/
└── hvigor-config.json5 # Hvigor 配置
9.2 example 工程的 build-profile.json5
{
"app": {
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.1.0(18)",
"runtimeOS": "HarmonyOS"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry"
}
]
}
关键配置:
compatibleSdkVersion: "5.1.0(18)"— 最低兼容的 SDK 版本runtimeOS: "HarmonyOS"— 运行时操作系统modules— 声明工程包含的模块
9.3 插件包的引用方式
在鸿蒙工程中,插件包通过 符号链接(symlink) 的方式被引用。Flutter-OHOS 构建工具会自动在 entry/oh_modules/ 目录下创建指向插件包 ohos/ 目录的符号链接:
entry/oh_modules/
└── flutter_libphonenumber_ohos/ → ../../ohos/ (symlink)
注意:不要手动复制插件包的
ohos/目录到 example 工程中,Flutter-OHOS 构建工具会自动管理符号链接。
十、从零创建鸿蒙平台包的步骤
10.1 完整创建流程
如果你要为其他 Flutter 插件创建鸿蒙平台实现,可以按以下步骤操作:
- 创建包目录
mkdir -p my_plugin_ohos/lib
mkdir -p my_plugin_ohos/ohos/src/main/ets/components/plugin
- 创建 pubspec.yaml
name: my_plugin_ohos
version: 1.0.0
environment:
sdk: ">=2.19.0 <4.0.0"
flutter: ">=3.0.0"
flutter:
plugin:
implements: my_plugin
platforms:
ohos:
package: com.example.my_plugin
pluginClass: MyPluginPlugin
dartPluginClass: MyPluginOhos
dependencies:
flutter:
sdk: flutter
my_plugin_platform_interface: ^1.0.0
- 创建 Dart 侧实现
// lib/my_plugin_ohos.dart
import 'package:flutter/services.dart';
import 'package:my_plugin_platform_interface/my_plugin_platform_interface.dart';
const _channel = MethodChannel('com.example/my_plugin_ohos');
class MyPluginOhos extends MyPluginPlatform {
static void registerWith() {
MyPluginPlatform.instance = MyPluginOhos();
}
// 实现抽象方法...
}
- 创建 ohos/oh-package.json5
{
"name": "my_plugin_ohos",
"version": "1.0.0",
"main": "index.ets",
"dependencies": {
"@ohos/flutter_ohos": "*"
}
}
- 创建 ohos/index.ets
import MyPluginPlugin
from './src/main/ets/components/plugin/MyPluginPlugin';
export default MyPluginPlugin;
- 创建 ArkTS 插件类
import {
FlutterPlugin, FlutterPluginBinding,
MethodCall, MethodCallHandler,
MethodChannel, MethodResult
} from '@ohos/flutter_ohos';
export default class MyPluginPlugin
implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
getUniqueClassName(): string { return 'MyPluginPlugin'; }
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(
binding.getBinaryMessenger(), 'com.example/my_plugin_ohos'
);
this.channel.setMethodCallHandler(this);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
this.channel?.setMethodCallHandler(null);
this.channel = null;
}
onMethodCall(call: MethodCall, result: MethodResult): void {
// 处理方法调用
result.notImplemented();
}
}
- 创建 ohos/module.json5
{
"module": {
"name": "my_plugin_ohos",
"type": "har",
"deviceTypes": ["default", "tablet"]
}
}
10.2 创建检查清单
完成创建后,逐项检查以下要素:
pubspec.yaml中implements指向正确的主包名dartPluginClass类名与 Dart 文件中的类名一致pluginClass类名与 ArkTS 文件中的类名一致- MethodChannel 通道名称在 Dart 和 ArkTS 两端完全一致
oh-package.json5的main指向index.etsindex.ets正确导出了插件类module.json5的type为har- Dart 类正确继承了
PlatformInterface的子类
十一、常见问题与排查
11.1 MethodChannel 通道名称不匹配
症状:调用 API 时无响应或抛出 MissingPluginException
排查:
// Dart 侧
const _channel = MethodChannel('com.bottlepay/flutter_libphonenumber_ohos');
// ArkTS 侧 — 必须完全一致
const CHANNEL_NAME: string = 'com.bottlepay/flutter_libphonenumber_ohos';
提示:通道名称是 大小写敏感 的,一个字符的差异都会导致通信失败。
11.2 registerWith() 未被调用
症状:FlutterLibphonenumberPlatform.instance 仍然是默认的 MethodChannelFlutterLibphonenumber
排查:
- 检查
pubspec.yaml中dartPluginClass是否正确 - 检查
registerWith()是否为static void方法 - 运行
flutter clean后重新构建
11.3 GeneratedPluginRegistrant 未包含插件
症状:ArkTS 侧的 GeneratedPluginRegistrant.ets 中没有导入插件
排查:
- 检查
pubspec.yaml中pluginClass是否正确 - 检查
oh-package.json5中name是否与包名一致 - 运行
flutter pub get重新生成
11.4 HAR 模块编译失败
症状:DevEco Studio 报告编译错误
排查:
- 检查
@ohos/flutter_ohos依赖是否正确声明 - 检查
module.json5的type是否为har - 检查 ArkTS 代码是否有语法错误
十二、本文涉及的文件清单
| 文件 | 路径 | 作用 |
|---|---|---|
| pubspec.yaml | flutter_libphonenumber_ohos/pubspec.yaml |
Flutter 包配置 |
| Dart 实现 | lib/flutter_libphonenumber_ohos.dart |
Dart 侧平台实现 |
| 包入口 | ohos/index.ets |
鸿蒙包入口文件 |
| 包配置 | ohos/oh-package.json5 |
鸿蒙包元数据 |
| 模块配置 | ohos/src/main/module.json5 |
模块类型声明 |
| 构建配置 | ohos/build-profile.json5 |
构建选项 |
| 构建脚本 | ohos/hvigorfile.ts |
HAR 构建任务 |
| 构建变量 | ohos/BuildProfile.ets |
编译时变量 |
| 插件入口 | ohos/src/main/ets/.../FlutterLibphonenumberPlugin.ets |
ArkTS 插件类 |
| 核心工具 | ohos/src/main/ets/.../PhoneNumberUtil.ets |
格式化/解析逻辑 |
| 自动注册 | example/ohos/.../GeneratedPluginRegistrant.ets |
自动生成的注册代码 |
总结
本文详细讲解了鸿蒙平台插件包 flutter_libphonenumber_ohos 的完整创建过程。关键要点回顾:
- 插件包由 Dart 侧(
lib/)和 原生侧(ohos/)两部分组成,通过 MethodChannel 通信 pubspec.yaml中的flutter.plugin配置是注册的核心,dartPluginClass实现 Dart 侧自动注册,pluginClass实现 ArkTS 侧自动注册ohos/目录使用 HAR 模块 类型,包含oh-package.json5、module.json5、index.ets等配置文件GeneratedPluginRegistrant.ets由 Flutter-OHOS 构建工具 自动生成,无需手动编写- 注册是 双端 的——Dart 侧通过
registerWith()注册平台实例,ArkTS 侧通过GeneratedPluginRegistrant注册插件到 FlutterEngine - 掌握了这套创建流程,你可以为 任何 Flutter 插件 创建鸿蒙平台实现包
下一篇我们将深入 init() 初始化流程,看看国家数据是如何从 ArkTS 侧加载到 Dart 侧的 CountryManager 中的。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- OpenHarmony 适配仓库:gitcode.com/oh-flutter/flutter_libphonenumber
- 开源鸿蒙跨平台社区:openharmonycrossplatform.csdn.net
- Flutter 联合插件官方文档:docs.flutter.dev - Federated plugins
- Flutter MethodChannel 文档:docs.flutter.dev - Platform channels
- plugin_platform_interface 包:pub.dev/packages/plugin_platform_interface
- Flutter-OHOS 项目:gitee.com/openharmony-sig/flutter_flutter
- OpenHarmony HAR 模块文档:developer.huawei.com - HAR
- Hvigor 构建工具:developer.huawei.com - Hvigor
- OHPM 包管理器:ohpm.openharmony.cn
- Google libphonenumber:github.com/google/libphonenumber
更多推荐



所有评论(0)