Flutter 三方库(Flutter-New-Badge)适配开源鸿蒙教程

Flutter 三方库(Flutter-New-Badge)适配鸿蒙教程

flutter_new_badger(应用图标角标插件)为例,完整讲解如何将一个现有 Flutter 插件适配到 OHOS 平台。


目录

  1. 背景知识
  2. 环境准备
  3. [OHOS 插件项目结构](#OHOS 插件项目结构)
    • [3.1 各平台目录结构对比](#3.1 各平台目录结构对比)
    • [3.2 Android ↔ iOS ↔ OHOS 概念映射](#3.2 Android ↔ iOS ↔ OHOS 概念映射)
    • [3.3 OHOS 目录文件详解(对照 Android)](#3.3 OHOS 目录文件详解(对照 Android))
    • [3.4 最小文件清单](#3.4 最小文件清单)
  4. [创建 OHOS 原生插件(ArkTS)](#创建 OHOS 原生插件(ArkTS))
  5. 模块入口与注册
  6. 插件打包配置
  7. [Pubspec.yaml 配置](#Pubspec.yaml 配置)
  8. [宿主 App 工程配置](#宿主 App 工程配置)
  9. 构建与运行
  10. 完整代码参考
  11. 常见问题

1. 背景知识

1.1 什么是 Flutter 插件

Flutter 插件通过 MethodChannel 实现 Dart 与原生平台的通信:

复制代码
Dart (MethodChannel.invokeMethod)
  → 原生端 (Java / Kotlin / Swift / ObjC)
  → OHOS (ArkTS)

原本 Flutter-New-Badger 已支持 Android、iOS、macOS,我们需要为其新增 OHOS 平台支持。

1.2 OHOS 角标 API

HarmonyOS 提供了 notificationManager.setBadgeNumber() API(API 10+),可直接设置应用图标角标,无需创建通知渠道、无需发布通知、无需申请权限,比 Android 的处理方式简洁很多。

typescript 复制代码
import { notificationManager } from '@kit.NotificationKit';

notificationManager.setBadgeNumber(5).then(() => {
  console.log('角标设置成功');
}).catch((err) => {
  console.error('角标设置失败', err);
});

1.3 Flutter for OHOS 工作原理

Flutter 社区为 OHOS 提供了独立的 Flutter 引擎分支 flutter_flutter,该引擎实现了与标准 Flutter 兼容的插件注册机制:

  • FlutterPlugin 接口:插件的生命周期管理
  • MethodChannel:与 Dart 层双向通信
  • MethodCallHandler:处理来自 Dart 层的方法调用

这些接口都封装在 @ohos/flutter_ohos 包中。


2. 环境准备

2.1 安装 DevEco Studio

下载并安装 DevEco Studio(当前推荐版本 6.1.0+),配置 HarmonyOS SDK。

2.2 安装 Flutter for OHOS

bash 复制代码
# 克隆 OHOS Flutter 引擎
git clone https://gitcode.com/openharmony-sig/flutter_flutter.git

# 配置环境变量
export FLUTTER_STORAGE_BASE_URL=https://download.ohos.com/huawei/ohos/flutter
export FLUTTER_HOME=/path/to/flutter_flutter
export PATH=$FLUTTER_HOME/bin:$PATH

# 验证
flutter --version

当前测试版本:Flutter 3.41.10-ohos-0.0.1-canary1,Dart 3.11.5

2.3 验证环境

bash 复制代码
# 创建测试工程
flutter create --project-name test_app test_app
cd test_app

# 添加 OHOS 平台
flutter build ohos --debug

# 确认 ohos/ 目录生成
ls ohos/
# 输出: AppScope  build-profile.json5  entry  hvigor  ...

2.4 快速创建 OHOS 插件脚手架

对于已有 Flutter 插件项目,可以直接用以下命令一键生成 OHOS 平台的目录结构和配置文件:

bash 复制代码
# 在插件项目根目录执行
cd /path/to/your_flutter_plugin

flutter create . --template=plugin --platforms=ohos

该命令会在插件根目录自动创建 ohos/ 目录,包含 index.etsoh-package.json5src/main/module.json5hvigorfile.ts 等必备文件的模板,开发者只需填充 FlutterNewBadgerPlugin.ets 的方法调用处理逻辑即可。

命令说明:

参数 作用
. 当前目录 在已有插件项目上追加平台
--template=plugin 固定值 指明生成的是 Flutter 插件项目模板
--platforms=ohos 目标平台 指定只生成 OHOS 平台代码(可组合:android,ios,ohos

注意 :如果插件目录下已有 ohos/ 文件夹,该命令会报错。可先暂存现有 ohos/,执行后再恢复修改。也可按第 3 节的手动方式逐一手动创建。


3. OHOS 插件项目结构

3.1 各平台目录结构对比

OHOS 适配遵循与 Android、iOS 完全一致的设计模式:在插件根目录创建以平台命名的同级目录,内部放置该平台的原生代码和配置文件。

复制代码
Flutter-New-Badger/
│
├── lib/                          # Dart 平台抽象层(各平台共享)
│   └── src/method_channels/
│       ├── flutter_new_badger_platform_interface.dart   # 抽象接口
│       └── flutter_new_badger_method_channel.dart       # MethodChannel 实现
│
├── android/                      # Android 平台
│   ├── build.gradle              # Gradle 构建配置
│   ├── settings.gradle
│   ├── src/
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       └── kotlin/ch/simonbraillard/flutter_new_badger/
│   │           └── FlutterNewBadgerPlugin.kt            # Kotlin 原生插件
│   └── ...
│
├── ios/                          # iOS 平台
│   ├── Classes/
│   │   └── FlutterNewBadgerPlugin.swift                 # Swift 原生插件
│   ├── Resources/
│   │   └── PrivacyInfo.xcprivacy
│   └── flutter_new_badger.podspec                       # CocoaPods 配置
│
├── macos/                        # macOS 平台
│   ├── Classes/
│   │   └── FlutterNewBadgerPlugin.swift                 # Swift 原生插件
│   ├── Resources/
│   │   └── PrivacyInfo.xcprivacy
│   └── flutter_new_badger.podspec                       # CocoaPods 配置
│
├── ohos/ 👈                      # OHOS 平台 --- 与 android/ ios/ 平级
│   ├── index.ets                 # 模块入口,导出插件类
│   ├── oh-package.json5          # OHOS 包配置 (相当于 Android 的 build.gradle)
│   ├── build-profile.json5       # 构建配置(可选)
│   ├── hvigorfile.ts             # 构建脚本 (相当于 Android 的 build.gradle)
│   ├── src/
│   │   └── main/
│   │       ├── module.json5      # HAR 模块配置 (相当于 Android 的 AndroidManifest.xml)
│   │       └── ets/
│   │           └── components/
│   │               └── plugin/
│   │                   └── FlutterNewBadgerPlugin.ets   # ArkTS 原生插件
│   └── ...
│
└── pubspec.yaml                  # Flutter 插件注册入口

3.2 Android ↔ iOS ↔ OHOS 概念映射

下表展示三个平台在 Flutter 插件中的概念对应关系,理解这张表可以大大降低 OHOS 适配的学习曲线:

角色 Android iOS / macOS OHOS
原生语言 Kotlin / Java Swift / Objective-C ArkTS (TypeScript 方言)
插件入口/导出 pluginClasspubspec.yaml 中声明 pluginClasspubspec.yaml 中声明 index.etsexport default ClassName
插件实现 实现 FlutterPlugin + MethodCallHandler 接口 实现 FlutterPlugin 协议 + handle 方法 实现 FlutterPlugin + MethodCallHandler 接口
引擎绑定回调 onAttachedToEngine(binding) register(with:) 静态方法 onAttachedToEngine(binding)
引擎解绑回调 onDetachedFromEngine(binding) 自动管理(ARC) onDetachedFromEngine(binding)
通道通信 MethodChannel(binaryMessenger, name) FlutterMethodChannel(name, messenger) MethodChannel(binaryMessenger, name)
参数读取 call.argument<T>("key") (call.arguments as? [String: Any])?["key"] call.argument('key') as type
结果返回 result.success(value) result(value) result.success(value)
错误返回 result.error(code, msg, details) FlutterError(code, msg, details) result.error(code, msg, details)
未实现方法 result.notImplemented() FlutterMethodNotImplemented result.notImplemented()
编译配置 build.gradle / build.gradle.kts podspec oh-package.json5 + hvigorfile.ts
模块配置 AndroidManifest.xml Info.plist(通过 podspec) module.json5
包类型 AAR(Android Archive) Framework(通过 CocoaPods) HAR(Harmony Archive)
测试目录 src/test/ Tests target src/ohosTest/(宿主工程)

3.3 OHOS 目录文件详解(对照 Android)

flutter_new_badger 项目中的实际文件逐一对照说明:

text 复制代码
ohos/                          ↔ android/
├── index.ets                  ↔ (无直接对应,Android 由 pluginClass 反射注册)
│   // 模块入口,导出插件类        // Android 通过 pubspec.yaml 的 pluginClass 反射加载
│
├── oh-package.json5           ↔ build.gradle / build.gradle.kts
│   // OHOS 包配置               // 声明包名、版本、入口文件
│   // main 指向 index.ets      // dependencies 管理依赖
│
├── build-profile.json5        ↔ (项目级 build.gradle)
│   // 构建配置(可选)           // apiType、artifactType 等
│
├── hvigorfile.ts              ↔ build.gradle (app层面)
│   // HAR 构建任务脚本           // 声明 system: harTasks
│
└── src/
    └── main/
        ├── module.json5        ↔ AndroidManifest.xml
        │   // HAR 模块配置         // name、type(har)、deviceTypes
        │
        └── ets/                ↔ kotlin/
            └── components/
                └── plugin/
                    └── FlutterNewBadgerPlugin.ets
                    // ArkTS 原生插件实现
                    // 与 FlutterNewBadgerPlugin.kt 对标

3.4 最小文件清单

OHOS 平台只需要 4 个核心文件 即可工作,其余文件(build-profile.json5hvigorfile.ts)可由宿主工程继承:

# 文件 必选 作用
1 ohos/index.ets 模块入口,export default 插件类
2 ohos/oh-package.json5 包元信息,声明入口和版本
3 ohos/src/main/module.json5 HAR 模块配置(module name、type、devices)
4 ohos/src/main/ets/components/plugin/FlutterNewBadgerPlugin.ets 原生插件实现(核心代码)

4. 创建 OHOS 原生插件(ArkTS)

4.1 导入依赖

typescript 复制代码
import {
  FlutterPlugin,
  FlutterPluginBinding,
  MethodCall,
  MethodCallHandler,
  MethodChannel,
  MethodResult,
} from '@ohos/flutter_ohos';
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
导入 来源 用途
FlutterPlugin @ohos/flutter_ohos 插件生命周期接口
FlutterPluginBinding @ohos/flutter_ohos 引擎绑定实例,提供 BinaryMessenger
MethodChannel @ohos/flutter_ohos 方法通道核心类
MethodCallHandler @ohos/flutter_ohos 处理 Dart 端方法调用的接口
MethodCall / MethodResult @ohos/flutter_ohos 方法调用请求/响应对象
notificationManager @kit.NotificationKit OHOS 角标 API
BusinessError @kit.BasicServicesKit 异步错误类型

4.2 实现插件类

typescript 复制代码
export default class FlutterNewBadgerPlugin implements FlutterPlugin, MethodCallHandler {
  private channel: MethodChannel | null = null;
  private static badgeCount: number = 0;

  constructor() {
  }

  // 必须实现:返回插件唯一标识类名
  getUniqueClassName(): string {
    return "FlutterNewBadgerPlugin"
  }

  // FlutterPlugin:引擎绑定回调
  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(
      binding.getBinaryMessenger(),  // 通信信使
      "flutter_new_badger"          // 通道名称,必须与 Dart 端一致
    );
    this.channel.setMethodCallHandler(this);
  }

  // FlutterPlugin:引擎解绑回调(清理资源)
  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    if (this.channel != null) {
      this.channel.setMethodCallHandler(null);
    }
  }

  // MethodCallHandler:处理来自 Dart 端的方法调用
  onMethodCall(call: MethodCall, result: MethodResult): void {
    // ... 见下文
  }
}
核心概念说明
  • 通道名称"flutter_new_badger" 必须与 Dart 端 MethodChannel('flutter_new_badger') 完全一致
  • getUniqueClassName():Flutter 引擎通过此方法识别唯一的插件实例
  • onAttachedToEngine:当插件被注册到 Flutter 引擎时回调,在此创建 MethodChannel
  • onDetachedFromEngine:当插件从引擎移除时回调,在此释放资源

4.3 实现 Method Call Handler

typescript 复制代码
onMethodCall(call: MethodCall, result: MethodResult): void {
  try {
    switch (call.method) {
      case 'setBadge': {
        const count = call.argument('count') as number;
        if (typeof count !== 'number' || count < 0) {
          result.error('INVALID_ARGUMENTS',
            'Badge count must be a non-negative number', null);
          return;
        }
        notificationManager.setBadgeNumber(count).then(() => {
          FlutterNewBadgerPlugin.badgeCount = count;  // 更新缓存
          result.success(null);                       // 通知 Dart 端成功
        }).catch((err: BusinessError) => {
          result.error('BADGE_ERROR', err.message, null);
        });
        break;
      }
      case 'removeBadge': {
        notificationManager.setBadgeNumber(0).then(() => {
          FlutterNewBadgerPlugin.badgeCount = 0;
          result.success(null);
        }).catch((err: BusinessError) => {
          result.error('BADGE_ERROR', err.message, null);
        });
        break;
      }
      case 'getBadge': {
        result.success(FlutterNewBadgerPlugin.badgeCount);
        break;
      }
      default: {
        result.notImplemented();  // 未实现的方法
        break;
      }
    }
  } catch (err) {
    const code: string = (err as Record<string, Object>)['code'] as string || 'BADGE_ERROR';
    const message: string = (err as Record<string, Object>)['message'] as string || String(err);
    result.error(code, message, null);
  }
}
方法通道对照表
方法名 参数 返回 实现
setBadge { count: number } void notificationManager.setBadgeNumber(count)
removeBadge void notificationManager.setBadgeNumber(0)
getBadge number 返回内存缓存值
设计要点
  1. 参数验证 :在 setBadge 中检查 count 是否为非负数字,防止无效值写入系统
  2. 异步错误处理notificationManager.setBadgeNumber() 返回 Promise,用 .catch() 捕获 BusinessError
  3. 内存缓存 :角标值用 static 变量缓存,应用重启后重置为 0
  4. 兜底异常捕获try/catch 包裹 switch,防止意外异常导致 Dart 端永久挂起

4.4 与 Android 实现的对比

方面 Android OHOS
API ShortcutBadger.applyCount(context, count) notificationManager.setBadgeNumber(count)
参数传递 call.argument<Int>("count") call.argument('count') as number
异步处理 无需(同步调用) Promise (.then/.catch)
异常类型 通用 Exception BusinessError
Context 依赖 需要 Application Context 不需要

5. 模块入口与注册

5.1 入口文件 ohos/index.ets

typescript 复制代码
import FlutterNewBadgerPlugin from './src/main/ets/components/plugin/FlutterNewBadgerPlugin';
export default FlutterNewBadgerPlugin;

这个文件是 OHOS 模块的入口点,Flutter 引擎通过 import 发现并注册插件。

5.2 模块配置 ohos/src/main/module.json5

json5 复制代码
{
  "module": {
    "name": "flutter_new_badger",    // 模块名,需与 oh-package.json5 中的 name 一致
    "type": "har",                   // HAR (Harmony Archive) 包类型
    "deviceTypes": [
      "default",                     // 支持手机
      "tablet"                       // 支持平板
    ]
  }
}
配置项说明
配置项 说明
name 与包名一致 需与 oh-package.json5name 字段匹配
type har 静态共享包,编译时打包到宿主应用中
deviceTypes ["default", "tablet"] 支持的设备类型

type: "har" 表示这是一个 Harmony Archive,与 Android 的 AAR、iOS 的 Framework 类似。

5.3 包配置 ohos/oh-package.json5

json5 复制代码
{
  "name": "flutter_new_badger",
  "version": "1.0.0",
  "description": "Flutter-New-Badger plugin for OHOS",
  "main": "index.ets",        // 入口文件
  "author": "",
  "license": "Apache-2.0",
  "dependencies": {}
}

main: "index.ets" 指定模块入口,与 index.ets 文件对应。

5.4 构建配置 ohos/build-profile.json5(可选)

对于简单的 HAR 插件,可以省略此文件,使用宿主工程的构建配置。如果需要自定义构建,可添加:

json5 复制代码
{
  "apiType": "stageMode",
  "buildOption": {
    "artifactType": "obfuscation"
  }
}

6. 插件打包配置

6.1 简化版 hvigorfile.ts

typescript 复制代码
import { harTasks } from '@ohos/hvigor-ohos-plugin';

export default {
  system: harTasks,  // HAR 构建任务
  plugins: []
};

6.2 项目级 hvigorconfig.ts

宿主工程根目录下的 hvigorconfig.ts 用于全局配置,插件不强制需要。


7. Pubspec.yaml 配置

在插件根目录的 pubspec.yaml 中添加 ohos 平台声明:

yaml 复制代码
flutter:
  plugin:
    platforms:
      android:
        package: ch.simonbraillard.flutter_new_badger
        pluginClass: FlutterNewBadgerPlugin
      ios:
        pluginClass: FlutterNewBadgerPlugin
      macos:
        pluginClass: FlutterNewBadgerPlugin
      ohos:                        # 新增 OHOS 平台
        pluginClass: FlutterNewBadgerPlugin    # 与 index.ets export default 的类名一致

Android ↔ OHOS pubspec.yaml 配置对比

平台 关键字段 说明
Android package ch.simonbraillard.flutter_new_badger Android 独有,对应 manifest 的 package
pluginClass FlutterNewBadgerPlugin 对应 Kotlin 类名
iOS / macOS pluginClass FlutterNewBadgerPlugin 对应 Swift 类名
OHOS pluginClass FlutterNewBadgerPlugin 对应 index.etsexport default 的类名

OHOS 的配置方式与 iOS 完全一致:只需要 pluginClass,不需要 package 字段。

关键说明

  • pluginClass 指向 ohos/index.etsexport default 的类名
  • Dart 层无需任何修改------原有的 MethodChannel 调用方式完全兼容
  • 增量/减量操作(incrementBadgeCount / decrementBadgeCount)在 Dart 层通过 getBadge + setBadge 组合实现,不涉及原生代码

Dart 端完整代码

dart 复制代码
// lib/src/method_channels/flutter_new_badger_method_channel.dart
class MethodChannelFlutterNewBadger extends FlutterNewBadgerPlatform {
  final methodChannel = const MethodChannel('flutter_new_badger');

  @override
  Future<void> setBadge(int count) async {
    await methodChannel.invokeMethod<void>('setBadge', {"count": count});
  }

  @override
  Future<void> removeBadge() async {
    await methodChannel.invokeMethod<void>('removeBadge');
  }

  @override
  Future<int?> getBadge() async {
    return await methodChannel.invokeMethod<int?>('getBadge');
  }
}

8. 宿主 App 工程配置

8.1 OHOS 端的依赖配置

在宿主应用的 example/ohos/oh-package.json5 中,需要声明对 Flutter OHOS 引擎的依赖:

json5 复制代码
{
  "name": "entry",
  "version": "1.0.0",
  "dependencies": {
    "@ohos/flutter_ohos": "file:../oh_modules/.ohpm/@ohos/flutter_ohos"
  }
}

此依赖由 flutter build ohos 命令自动生成,开发者通常不需要手动修改。

8.2 EntryAbility 配置

example/ohos/entry/src/main/ets/entryability/EntryAbility.ets 需要正确加载 Flutter:

typescript 复制代码
import { FlutterAbility } from '@ohos/flutter_ohos';

export default class EntryAbility extends FlutterAbility {
  // FlutterAbility 自动完成插件注册和 Flutter 引擎初始化
}

8.3 完整构建流程

复制代码
Flutter 插件适配 OHOS --- 完整构建流程
│
├── 方式一:手动创建(见第 3 节)
│   ├── 创建 ohos/ 目录及上述文件
│   └── 在 pubspec.yaml 添加 ohos 平台
│
├── 方式二:命令行自动生成(推荐)
│   └── flutter create . --template=plugin --platforms=ohos
│       ├── 自动创建 ohos/ 目录及模板文件
│       └── 自动更新 pubspec.yaml 的 platforms 配置
│       └── 手动修改 FlutterNewBadgerPlugin.ets 填充业务逻辑
│
├── 3. flutter pub get 刷新依赖
│
宿主应用集成
│
├── 4. 在 example/pubspec.yaml 引用插件(git / path)
├── 5. flutter pub get
├── 6. flutter build ohos --debug     # 构建 OHOS 产物
└── 7. 用 DevEco Studio 打开 ohos/ 目录并运行

9. 构建与运行

9.1 开发阶段

bash 复制代码
# 0. (仅首次) 生成 OHOS 插件脚手架(自动创建 ohos/ 目录 + 更新 pubspec.yaml)
cd Flutter-New-Badger
flutter create . --template=plugin --platforms=ohos

# 1. 在插件目录安装依赖
cd Flutter-New-Badger
flutter pub get

# 2. 在示例应用目录
cd example

# 3. 安装依赖
flutter pub get

# 4. 构建 OHOS 产物
flutter build ohos --debug

# 5. 用 DevEco Studio 打开 example/ohos/ 目录
open example/ohos/ -a "DevEco-Studio"

# 6. 在 DevEco Studio 中连接设备或模拟器
# 7. 点击 Run 运行

9.2 发布阶段

插件作为一个完整的 Flutter 插件包发布,使用者只需在 pubspec.yaml 中添加依赖:

yaml 复制代码
dependencies:
  flutter_new_badger:
    git:
      url: https://gitcode.com/oh-flutter/Flutter-New-Badger.git
      ref: main

或本地路径:

yaml 复制代码
dependencies:
  flutter_new_badger:
    path: ../Flutter-New-Badger

10. 完整代码参考

10.1 文件清单

文件 行数 作用
ohos/index.ets 4 模块入口,导出插件类
ohos/src/main/ets/components/plugin/FlutterNewBadgerPlugin.ets 76 原生插件核心实现
ohos/oh-package.json5 8 包元信息
ohos/src/main/module.json5 9 HAR 模块配置
ohos/hvigorfile.ts 5 构建任务脚本
pubspec.yaml(新增 ohos 平台) 1 行修改 Flutter 插件平台注册

10.2 各文件完整内容

ohos/src/main/ets/components/plugin/FlutterNewBadgerPlugin.ets

typescript 复制代码
import {
  FlutterPlugin,
  FlutterPluginBinding,
  MethodCall,
  MethodCallHandler,
  MethodChannel,
  MethodResult,
} from '@ohos/flutter_ohos';
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';

export default class FlutterNewBadgerPlugin implements FlutterPlugin, MethodCallHandler {
  private channel: MethodChannel | null = null;
  private static badgeCount: number = 0;

  getUniqueClassName(): string {
    return "FlutterNewBadgerPlugin"
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_new_badger");
    this.channel.setMethodCallHandler(this)
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    if (this.channel != null) {
      this.channel.setMethodCallHandler(null)
    }
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    try {
      switch (call.method) {
        case 'setBadge': {
          const count = call.argument('count') as number;
          if (typeof count !== 'number' || count < 0) {
            result.error('INVALID_ARGUMENTS', 'Badge count must be a non-negative number', null);
            return;
          }
          notificationManager.setBadgeNumber(count).then(() => {
            FlutterNewBadgerPlugin.badgeCount = count;
            result.success(null);
          }).catch((err: BusinessError) => {
            result.error('BADGE_ERROR', err.message, null);
          });
          break;
        }
        case 'removeBadge': {
          notificationManager.setBadgeNumber(0).then(() => {
            FlutterNewBadgerPlugin.badgeCount = 0;
            result.success(null);
          }).catch((err: BusinessError) => {
            result.error('BADGE_ERROR', err.message, null);
          });
          break;
        }
        case 'getBadge': {
          result.success(FlutterNewBadgerPlugin.badgeCount);
          break;
        }
        default: {
          result.notImplemented();
          break;
        }
      }
    } catch (err) {
      const code: string = (err as Record<string, Object>)['code'] as string || 'BADGE_ERROR';
      const message: string = (err as Record<string, Object>)['message'] as string || String(err);
      result.error(code, message, null);
    }
  }
}

ohos/index.ets

typescript 复制代码
import FlutterNewBadgerPlugin from './src/main/ets/components/plugin/FlutterNewBadgerPlugin';
export default FlutterNewBadgerPlugin;

ohos/oh-package.json5

json5 复制代码
{
  "name": "flutter_new_badger",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "index.ets",
  "author": "",
  "license": "Apache-2.0",
  "dependencies": {}
}

ohos/src/main/module.json5

json5 复制代码
{
  "module": {
    "name": "flutter_new_badger",
    "type": "har",
    "deviceTypes": [
      "default",
      "tablet"
    ]
  }
}

11. 常见问题

Q1: 构建时提示 Cannot find module '@ohos/flutter_ohos'

原因:宿主工程的 OHOS 模块未正确配置 Flutter 引擎依赖。

解决 :在宿主工程的 ohos/oh-package.json5entry/oh-package.json5 中添加:

json5 复制代码
"dependencies": {
  "@ohos/flutter_ohos": "file:../oh_modules/.ohpm/@ohos/flutter_ohos"
}

然后重新执行 flutter build ohos --debug

Q2: 插件注册后没有被调用

原因 :常见于 index.ets 导出方式错误,或 pubspec.yaml 中的 pluginClass 不匹配。

检查清单

  • ohos/index.ets 使用 export default ClassName
  • pubspec.yamlohos.pluginClass 与该类名一致
  • 通道名称在 Dart 端和 OHOS 端完全一致

Q3: notificationManager.setBadgeNumber() 返回错误

原因:API 版本或设备限制。

解决

  • 确保设备 ROM 支持 API 10+
  • 检查设备是否有通知权限(虽然设置角标不需要,但个别厂商可能有差异)
  • 使用 try/catch 捕获 BusinessError

Q4: 应用重启后角标丢失

原因getBadge 返回的是内存缓存值,非系统级持久化查询。

默认行为

复制代码
应用运行 → setBadge(5) → 缓存=5,系统角标=5
应用杀死 → 系统保留角标=5(由系统管理)
应用重启 → 缓存=0,但系统角标仍为5

如需精确值,需要通过系统 API 查询角标状态(当前 OHOS 不提供此类查询 API)。


附录

适配工作量的量化统计

维度 变更内容 文件数 代码行数
原生实现 新建 OHOS ArkTS 插件 4 个 OHOS 文件 ~100 行
注册配置 pubspec.yaml 添加 ohos 平台 1 行修改 1 行
Dart 层 无需修改 0 0
文档 新增中英文 README 2 个文档 ~400 行

核心原则总结

  1. Dart 层零修改 ------ MethodChannel 是跨平台抽象,OHOS 适配只需替换原生端实现

  2. ArkTS 遵循标准接口 ------ 实现 FlutterPlugin + MethodCallHandler 即可


本文档基于 flutter_new_badger 项目的实际适配经验编写,相关代码可在 oh-flutter/Flutter-New-Badger 查看完整源码。

相关推荐
二蛋和他的大花14 小时前
高德地图 Flutter 插件:跨 Android / iOS / HarmonyOS 的完整实现
android·flutter·ios
不爱吃糖的程序媛15 小时前
鸿蒙Flutter 三方库 country_codes 的 适配实战
flutter·华为·harmonyos
●VON15 小时前
鸿蒙Flutter实战:Markdown编辑与预览实时切换
flutter·华为·harmonyos·鸿蒙
sbjdhjd15 小时前
从 0 到 1 构建高可用企业级 NoSql 数据库 Redis 集群
linux·运维·redis·云原生·kubernetes·开源·云计算
不羁的木木15 小时前
ArkUI实战演练04-状态管理与数据驱动
harmonyos
坚果的博客15 小时前
AtomCode 助力开源鸿蒙跨平台三方库生态共建
华为·开源·harmonyos
GitCode官方15 小时前
《开源友的聊》第二季,回来了。
人工智能·开源·atomgit
学点程序15 小时前
HyperFrames:用 HTML 生成视频的开源渲染框架
前端·开源·html·音视频
枫叶丹415 小时前
【HarmonyOS 6.0】Live View Kit深度解析:实况胶囊尾部图标的设计哲学与实现全流程
开发语言·华为·harmonyos