Flutter三方库适配OpenHarmony【flutter_web_auth】— FlutterPlugin 与 AbilityAware 双接口实现
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.netflutter_web_auth 的 OpenHarmony 实现需要同时实现三个接口这比 secure_application(只需要两个接口)多了一个 AbilityAware。为什么?因为打开浏览器需要,而不是普通的 ApplicationContext。这篇把三个接口的职责和实现细
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
flutter_web_auth 的 OpenHarmony 实现需要同时实现 三个接口:FlutterPlugin、MethodCallHandler、AbilityAware。这比 secure_application(只需要两个接口)多了一个 AbilityAware。为什么?因为打开浏览器需要 UIAbilityContext,而不是普通的 ApplicationContext。
这篇把三个接口的职责和实现细节都讲清楚。
一、三接口组合的设计意图
1.1 类声明
export default class FlutterWebAuthPlugin implements FlutterPlugin, MethodCallHandler, AbilityAware {
private channel: MethodChannel | null = null;
private ability: UIAbility | null = null;
private static callbacks: Map<string, MethodResult> = new Map();
// ...
}
1.2 三个接口的职责

1.3 为什么需要 AbilityAware
// 打开浏览器需要 UIAbilityContext
context.openLink(url); // context 来自 UIAbility
// 普通的 ApplicationContext 不能调用 openLink
// binding.getApplicationContext().openLink(url); // ❌ 没有这个方法
| API | 需要的 Context 类型 | 来源 |
|---|---|---|
| openLink | UIAbilityContext | AbilityAware → UIAbility.context |
| startAbility | UIAbilityContext | AbilityAware → UIAbility.context |
| getLastWindow | ApplicationContext | FlutterPluginBinding |
💡 这就是 flutter_web_auth 和 secure_application 的核心架构差异。secure_application 只需要 ApplicationContext 来获取窗口,所以不需要 AbilityAware。flutter_web_auth 需要 UIAbilityContext 来打开浏览器,所以必须实现 AbilityAware。
二、onAttachedToEngine:MethodChannel 创建
2.1 实现
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_web_auth");
this.channel.setMethodCallHandler(this);
console.info(TAG, 'onAttachedToEngine called');
}
2.2 执行时机
Flutter 引擎启动
↓
框架扫描已注册的插件
↓
调用 onAttachedToEngine(binding)
↓
创建 MethodChannel + 注册 Handler
2.3 通道名称
new MethodChannel(binding.getBinaryMessenger(), "flutter_web_auth");
| 端 | 通道名称 | 必须一致 |
|---|---|---|
| Dart | MethodChannel('flutter_web_auth') |
✅ |
| OpenHarmony | new MethodChannel(messenger, "flutter_web_auth") |
✅ |
2.4 与 flutter_speech 的对比
// flutter_web_auth
new MethodChannel(binding.getBinaryMessenger(), "flutter_web_auth");
// flutter_speech
new MethodChannel(binding.getBinaryMessenger(), "speech_recognition");
// secure_application
new MethodChannel(binding.getBinaryMessenger(), "secure_application");
每个插件的通道名称都不同,确保消息不会串。
三、onAttachedToAbility:UIAbility 引用获取
3.1 实现
onAttachedToAbility(binding: AbilityPluginBinding): void {
this.ability = binding.getAbility();
console.info(TAG, 'onAttachedToAbility called, ability is set');
}
3.2 AbilityPluginBinding 提供的能力
interface AbilityPluginBinding {
getAbility(): UIAbility; // 获取 UIAbility 引用
}
3.3 调用时序
onAttachedToEngine(binding) ← 先调用
↓
onAttachedToAbility(binding) ← 后调用
两个方法的调用顺序是固定的:先 Engine,后 Ability。这意味着在 onAttachedToEngine 中 this.ability 还是 null。
3.4 时序问题
时间线:
t0: onAttachedToEngine → channel 创建 ✅, ability = null
t1: onAttachedToAbility → ability 设置 ✅
t2: 用户调用 authenticate → 需要 ability.context
如果用户在 t0 和 t1 之间调用 authenticate,ability 还是 null,会触发 NO_CONTEXT 错误。实际上这种情况几乎不会发生,因为 t0 和 t1 之间的间隔极短。
四、onDetachedFromEngine / onDetachedFromAbility
4.1 onDetachedFromEngine
onDetachedFromEngine(_binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null);
}
}
4.2 onDetachedFromAbility
onDetachedFromAbility(): void {
this.ability = null;
console.info(TAG, 'onDetachedFromAbility called');
}
4.3 清理顺序
onDetachedFromAbility() ← 先调用
↓
onDetachedFromEngine() ← 后调用
与 attach 相反:先 detach Ability,后 detach Engine。
4.4 清理职责划分
| 方法 | 清理内容 |
|---|---|
| onDetachedFromAbility | 置空 ability 引用 |
| onDetachedFromEngine | 注销 MethodCallHandler |
4.5 为什么不清理 static callbacks
// 注意:没有清理 static callbacks
onDetachedFromEngine(_binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null);
}
// 没有 FlutterWebAuthPlugin.callbacks.clear()
}
因为 callbacks 是 static 的,它的生命周期不绑定到插件实例。Dart 层的 _cleanUpDanglingCalls 会负责清理。
五、与 secure_application 的架构差异对比
5.1 接口对比
| 维度 | flutter_web_auth | secure_application |
|---|---|---|
| FlutterPlugin | ✅ | ✅ |
| MethodCallHandler | ✅ | ✅ |
| AbilityAware | ✅ | ❌ |
| 接口总数 | 3 | 2 |
5.2 Context 获取方式对比
// flutter_web_auth:通过 AbilityAware 获取 UIAbilityContext
onAttachedToAbility(binding: AbilityPluginBinding): void {
this.ability = binding.getAbility();
// this.ability.context → UIAbilityContext
}
// secure_application:通过 FlutterPluginBinding 获取 ApplicationContext
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.context = binding.getApplicationContext();
// this.context → ApplicationContext
}
5.3 为什么不同
| 插件 | 需要的操作 | 需要的 Context | 获取方式 |
|---|---|---|---|
| flutter_web_auth | openLink 打开浏览器 | UIAbilityContext | AbilityAware |
| secure_application | getLastWindow 获取窗口 | ApplicationContext | FlutterPluginBinding |
| flutter_speech | 创建语音识别引擎 | UIAbilityContext | AbilityAware |
5.4 经验法则
📌 如果你的插件需要与 UI 交互(打开页面、弹窗、启动其他应用),就需要 AbilityAware。如果只需要后台操作(窗口属性、文件读写),ApplicationContext 就够了。
六、成员变量分析
6.1 实例变量
private channel: MethodChannel | null = null;
private ability: UIAbility | null = null;
| 变量 | 类型 | 初始值 | 设置时机 | 清理时机 |
|---|---|---|---|---|
| channel | MethodChannel | null | onAttachedToEngine | onDetachedFromEngine |
| ability | UIAbility | null | onAttachedToAbility | onDetachedFromAbility |
6.2 静态变量
private static callbacks: Map<string, MethodResult> = new Map();
| 变量 | 类型 | 生命周期 | 清理方式 |
|---|---|---|---|
| callbacks | Map<string, MethodResult> | 应用进程 | cleanUpDanglingCalls / onNewWant |
6.3 为什么 callbacks 是 static
场景:
1. FlutterWebAuthPlugin 实例 A 调用 authenticate → 存入 callbacks
2. 浏览器打开,用户认证
3. 系统通过 onNewWant 回调 → 需要从 callbacks 中取出 result
4. onNewWant 是 static 方法 → 只能访问 static 变量
如果 callbacks 不是 static,onNewWant(static 方法)就无法访问它。
七、getUniqueClassName 方法
7.1 实现
getUniqueClassName(): string {
return "FlutterWebAuthPlugin"
}
7.2 作用
Flutter-OHOS 框架用这个方法来唯一标识插件,防止重复注册。
7.3 命名规范
| 插件 | getUniqueClassName |
|---|---|
| flutter_web_auth | “FlutterWebAuthPlugin” |
| secure_application | “SecureApplicationPlugin” |
| flutter_speech | “FlutterSpeechRecognitionPlugin” |
返回值通常与类名相同。
八、构造函数
8.1 实现
constructor() {
}
空构造函数。Flutter-OHOS 框架通过反射创建插件实例,所以构造函数不能有参数。
8.2 初始化时机
| 操作 | 时机 |
|---|---|
| 创建实例 | 框架反射调用 constructor() |
| 设置 channel | onAttachedToEngine |
| 设置 ability | onAttachedToAbility |
| 可以处理方法调用 | onAttachedToAbility 之后 |
总结
本文详细分析了 flutter_web_auth 的三接口实现:
- FlutterPlugin:管理 MethodChannel 的创建和销毁
- MethodCallHandler:处理 Dart 层的方法调用
- AbilityAware:获取 UIAbility 引用,用于 openLink
- static callbacks:跨实例共享认证回调
- 与 secure_application 的差异:需要 UIAbilityContext vs ApplicationContext
下一篇我们讲深度链接机制——OpenHarmony 的 Want 和 skills 配置。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- FlutterPlugin 接口文档
- AbilityAware 接口
- UIAbilityContext
- ApplicationContext
- flutter_web_auth OpenHarmony 源码
- secure_application OpenHarmony 源码
- Flutter MethodChannel
- 开源鸿蒙跨平台社区

Flutter 插件平台通道架构
更多推荐

所有评论(0)