Flutter/OpenHarmony 三方库适配实战:flutter_local_notifications 本地通知
Flutter/OpenHarmony 三方库适配实战:flutter_local_notifications 本地通知
通知看起来只是“弹一条消息”,但在不同系统上,权限、通知槽位、通知 ID、取消策略和点击事件分别由不同 API 管理。flutter_local_notifications 的跨平台 API 已经把这些差异封装在 Dart 层,本次 OHOS 适配的任务就是把公开的 Dart 契约接到 @ohos.notificationManager,同时明确哪些能力首版不做。
一、项目信息与适配目标
| 项目 | 内容 |
|---|---|
| 仓库名称 | flutter_local_notifications |
| AtomGit 适配仓库 | https://atomgit.com/oh-flutter/flutter_local_notifications |
| 上游版本 | 22.3.2 |
| OHOS 适配 TAG | 22.3.2-ohos-1.0.0-beta.1 |
| 适配分支 | main |
| 方法通道 | dexterous.com/flutter/local_notifications |
| 原生模块 | OHOS HAR,入口类 FlutterLocalNotificationsPlugin |
首版支持:
| 能力 | OHOS 实现 |
|---|---|
| 初始化 | 查询通知开关状态 |
| 请求权限 | 调用系统通知授权页面 |
show() | 发布立即通知,同 ID 更新 |
cancel() | 按 ID 取消 |
cancelAll() | 取消当前应用全部通知 |
首版不支持定时通知、重复通知、后台启动、通知点击回调和 payload 启动事件。未实现的方法返回明确错误,不会伪造成功。
二、保留上游调用方式
业务代码仍然使用原来的 FlutterLocalNotificationsPlugin:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
Future<void> showOrderNotification() async {
final FlutterLocalNotificationsPlugin plugin =
FlutterLocalNotificationsPlugin();
final OhosFlutterLocalNotificationsPlugin? ohos =
plugin.resolvePlatformSpecificImplementation<
OhosFlutterLocalNotificationsPlugin>();
final enabled = await ohos?.requestPermissions() ?? false;
if (!enabled) {
return;
}
await plugin.show(
id: 1,
title: '订单状态',
body: '订单已发货',
payload: 'orders/1',
);
}
initialize() 在 OHOS 分支直接进入 OHOS 实现,不需要业务代码再创建一套 OHOS 专用对象:
if (isOhosPlatform()) {
return await resolvePlatformSpecificImplementation<
OhosFlutterLocalNotificationsPlugin
>()
?.initialize();
}
pubspec.yaml 中的 OHOS 声明是插件被 Flutter 工具链识别的关键:
flutter:
plugin:
platforms:
ohos:
pluginClass: FlutterLocalNotificationsPlugin
dartPluginClass: OhosFlutterLocalNotificationsPlugin
三、Dart 注册类只负责契约转换
OHOS Dart 类实现初始化、授权、发布和取消四个公开能力:
class OhosFlutterLocalNotificationsPlugin
extends FlutterLocalNotificationsPlatform {
static const MethodChannel channel = MethodChannel(
'dexterous.com/flutter/local_notifications',
);
static void registerWith() {
FlutterLocalNotificationsPlatform.instance =
OhosFlutterLocalNotificationsPlugin();
}
Future<bool> initialize() async {
return await channel.invokeMethod<bool>('initialize') ?? false;
}
Future<bool> requestPermissions() async {
return await channel.invokeMethod<bool>('requestPermissions') ?? false;
}
Future<void> show({
required int id,
String? title,
String? body,
String? payload,
}) {
return channel.invokeMethod('show', <String, Object?>{
'id': id,
'title': title,
'body': body,
'payload': payload ?? '',
});
}
Future<void> cancel({required int id}) {
return channel.invokeMethod('cancel', id);
}
Future<void> cancelAll() {
return channel.invokeMethod('cancelAll');
}
}
这里保留 payload 字段是为了兼容上游调用签名,但 OHOS 首版没有把 payload 注入系统通知点击事件。文档明确这一点,避免业务把“发布成功”误认为“点击回调已接通”。
四、ArkTS 层:方法分发和生命周期
原生入口实现 FlutterPlugin、MethodCallHandler 和 AbilityAware:
const CHANNEL = 'dexterous.com/flutter/local_notifications';
export default class FlutterLocalNotificationsPlugin
implements FlutterPlugin, MethodCallHandler, AbilityAware {
private channel: MethodChannel | null = null;
private uiAbilityContext: common.UIAbilityContext | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(
binding.getBinaryMessenger(),
CHANNEL,
);
this.channel.setMethodCallHandler(this);
}
onAttachedToAbility(binding: AbilityPluginBinding): void {
this.uiAbilityContext = binding.getAbility().context;
}
onDetachedFromAbility(): void {
this.uiAbilityContext = null;
}
}
initialize 直接读取通知开关:
case 'initialize':
notificationManager.isNotificationEnabled()
.then((enabled: boolean): void => result.success(enabled))
.catch((error: ESObject): void => this.errorResult(result, error));
return;
通知授权需要当前 UIAbilityContext。已授权时立即返回 true,未授权时请求系统通知页面:
private requestPermissions(result: MethodResult): void {
notificationManager.isNotificationEnabled()
.then((enabled: boolean): void => {
if (enabled) {
result.success(true);
return;
}
const context = this.uiAbilityContext;
if (context === null) {
result.error(
'ability_context_missing',
'UIAbilityContext is not available.',
null,
);
return;
}
notificationManager.requestEnableNotification(context)
.then((): Promise<boolean> =>
notificationManager.isNotificationEnabled())
.then((nowEnabled: boolean): void => result.success(nowEnabled));
});
}
这样返回值反映用户完成授权后的真实状态,而不是请求页面是否曾经显示过。
五、发布一条通知
show() 先再次检查通知开关,避免用户在设置页关闭通知后静默失败。通知内容使用基础文本类型,槽位使用服务信息:
private show(call: MethodCall, result: MethodResult): void {
notificationManager.isNotificationEnabled()
.then((enabled: boolean): void => {
if (!enabled) {
result.error(
'notification_disabled',
'Notification permission is not enabled.',
null,
);
return;
}
const request: notificationManager.NotificationRequest = {
id: Number(call.argument('id')),
notificationSlotType:
notificationManager.SlotType.SERVICE_INFORMATION,
content: {
notificationContentType:
notificationManager.ContentType
.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: String(call.argument('title') ?? ''),
text: String(call.argument('body') ?? ''),
},
},
};
notificationManager.publish(request)
.then((): void => result.success(null));
});
}
同一个 ID 再次 publish 时由系统按通知 ID 更新,业务不需要额外维护 OHOS 专用 ID 表。取消和全部取消直接使用系统 API:
case 'cancel':
notificationManager.cancel(Number(call.argument('id')))
.then((): void => result.success(null));
return;
case 'cancelAll':
notificationManager.cancelAll()
.then((): void => result.success(null));
return;
六、为什么首版不做定时和点击回调
上游 API 的 zonedSchedule()、periodicallyShow() 依赖后台调度和重复任务;点击回调还涉及系统通知事件、进程启动方式和 payload 恢复。OHOS 首版只实现了前台立即通知,未实现的方法走 notImplemented() 或明确错误,这样业务可以在日志中看到“能力缺失”,而不是收到一个永远不触发的回调。
当前能力边界:
立即通知 支持
按 ID 取消 支持
全部取消 支持
定时通知 不支持
重复通知 不支持
点击回调 不支持
后台启动 不支持
payload 恢复 不支持
后续版本如果接入 OHOS 后台任务和通知事件,需要同时补充 Dart 启动详情、后台 isolate 回调和系统事件桥接,不能只把定时方法改成 show()。
七、测试、构建和真实截图
新增测试覆盖 OHOS 注册、初始化、授权、show、cancel 和 cancelAll 通道:
flutter test \
test/ohos_flutter_local_notifications_test.dart \
test/ohos_plugin_metadata_test.dart
结果:All tests passed。
flutter analyze
结果:无 error。
示例工程的 OHOS HAP 已执行:
cd flutter_local_notifications/example
flutter build hap --debug
hdc install -r ohos/entry/build/default/outputs/default/entry-default-unsigned.hap
hdc shell aa start -a EntryAbility -b com.example.flutter_local_notifications_example

截图中可以看到示例首页和通知操作入口。实际发布通知时,系统通知中心的表现还取决于用户是否授权、系统版本和通知设置。
八、常见问题
- 页面启动后立即调用
show(),但没有通知:先调用 OHOS 的requestPermissions()并检查isNotificationEnabled()。 requestPermissions()返回ability_context_missing:检查 Ability 是否绑定,确认插件没有只保存 ApplicationContext。- 取消无效:检查传入的 ID 是否与发布时的
id完全一致。 - 点击通知没有跳转:首版尚未接通通知点击事件,应使用业务自己的页面恢复机制。
- 定时通知无效:当前版本不支持,需要等待后续后台任务适配。
社区
- OpenHarmony Flutter 社区:https://atomgit.com/oh-flutter
- CPF-Flutter 社区:https://atomgit.com/CPF-Flutter
- 本适配仓库讨论区:https://atomgit.com/oh-flutter/flutter_local_notifications/issues
欢迎提交设备型号、系统版本、通知设置和 hilog 日志,一起完善 OHOS 本地通知适配。
更多推荐



所有评论(0)