Flutter三方库适配OpenHarmony【flutter_web_auth】— EntryAbility 深度链接回调集成

前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

flutter_web_auth 在 OpenHarmony 上有一个其他平台没有的要求:宿主应用必须手动修改 EntryAbility 代码。Android 只需要在 Manifest 里加一段 XML,iOS 什么都不用改。但 OpenHarmony 需要开发者在 EntryAbility.ets 中写几行代码来转发深度链接回调。

这篇把集成代码的每一行都讲清楚,以及为什么非得这么做。

一、EntryAbility 的标准模式

1.1 未集成前的 EntryAbility

typescript 复制代码
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    GeneratedPluginRegistrant.registerWith(flutterEngine);
  }
}

这是一个标准的 Flutter-OHOS 应用入口。FlutterAbility 是 Flutter-OHOS 框架提供的基类,封装了 Flutter 引擎的初始化和渲染。

1.2 集成后的 EntryAbility

typescript 复制代码
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import { AbilityConstant, Want } from '@kit.AbilityKit';
import FlutterWebAuthPlugin from 'flutter_web_auth';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    GeneratedPluginRegistrant.registerWith(flutterEngine);
  }

  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    super.onNewWant(want, launchParam);
    FlutterWebAuthPlugin.onNewWant(want);
  }

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    super.onCreate(want, launchParam);
    FlutterWebAuthPlugin.onNewWant(want);
  }
}

1.3 新增的内容

新增项 代码 作用
import Want import { AbilityConstant, Want } from '@kit.AbilityKit' Want 类型定义
import Plugin import FlutterWebAuthPlugin from 'flutter_web_auth' 插件类引用
onNewWant 重写方法 处理 App 在前台时的深度链接
onCreate 重写方法 处理 App 冷启动时的深度链接

二、onNewWant 回调:App 已在前台

2.1 触发场景

复制代码
1. App 正在运行(前台或后台)
2. 用户在浏览器中完成认证
3. 浏览器重定向到 myapp://callback?code=abc
4. 系统找到已有的 EntryAbility 实例(singleton)
5. 调用 onNewWant(want)

2.2 实现

typescript 复制代码
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  super.onNewWant(want, launchParam);
  FlutterWebAuthPlugin.onNewWant(want);
}

2.3 为什么要调用 super

typescript 复制代码
super.onNewWant(want, launchParam);  // 必须调用

FlutterAbility.onNewWant 可能有自己的处理逻辑(比如更新 Flutter 引擎的路由)。不调用 super 可能导致其他功能异常。

2.4 FlutterWebAuthPlugin.onNewWant 的作用

typescript 复制代码
// 插件中的静态方法
static onNewWant(want: Want): void {
  const uri = want.uri;
  if (!uri) return;
  
  const schemeEnd = uri.indexOf('://');
  if (schemeEnd < 0) return;
  const scheme = uri.substring(0, schemeEnd);
  
  if (FlutterWebAuthPlugin.callbacks.has(scheme)) {
    const pendingResult = FlutterWebAuthPlugin.callbacks.get(scheme);
    FlutterWebAuthPlugin.callbacks.delete(scheme);
    pendingResult.success(uri);
  }
}

从 want.uri 中提取 Scheme,在 callbacks Map 中查找对应的 MethodResult,返回认证结果。

三、onCreate 中的 Want 处理

3.1 触发场景

复制代码
1. App 没有在运行(被系统杀掉或从未启动)
2. 用户在浏览器中完成认证
3. 浏览器重定向到 myapp://callback?code=abc
4. 系统创建新的 EntryAbility 实例
5. 调用 onCreate(want)

3.2 实现

typescript 复制代码
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  super.onCreate(want, launchParam);
  FlutterWebAuthPlugin.onNewWant(want);
}

3.3 冷启动场景的问题

复制代码
冷启动时序:
t0: onCreate(want) → FlutterWebAuthPlugin.onNewWant(want)
    但此时 callbacks Map 是空的!
    因为 App 刚启动,还没有调用过 authenticate()
    → onNewWant 找不到匹配的 callback → 静默忽略

📌 冷启动场景下认证回调会丢失。这是所有平台都存在的问题------如果 App 在浏览器认证期间被系统杀掉,认证结果就无法回传。实际上这种情况很少发生,因为认证过程通常很快。

3.4 为什么还要在 onCreate 中处理

即使冷启动场景下 callbacks 为空,仍然建议在 onCreate 中调用 onNewWant:

  1. 防御性编程:万一未来有其他逻辑需要处理
  2. 一致性:所有深度链接入口都统一处理
  3. 低成本:callbacks 为空时 onNewWant 直接返回,没有副作用

四、FlutterWebAuthPlugin.onNewWant 静态方法设计

4.1 为什么是 static

typescript 复制代码
static onNewWant(want: Want): void { ... }
如果是实例方法 如果是静态方法
需要获取插件实例的引用 直接通过类名调用
EntryAbility 需要知道如何获取实例 EntryAbility 只需要 import 类
耦合度高 耦合度低

4.2 调用方式对比

typescript 复制代码
// 静态方法(当前实现)✅
FlutterWebAuthPlugin.onNewWant(want);

// 如果是实例方法(假设)❌
// 需要先获取插件实例,非常麻烦
const plugin = FlutterEngine.getPlugin("FlutterWebAuthPlugin");
plugin.onNewWant(want);

4.3 static 方法访问 static 变量

typescript 复制代码
static onNewWant(want: Want): void {
  // 只能访问 static 成员
  FlutterWebAuthPlugin.callbacks.has(scheme);  // ✅ static 变量
  // this.channel  // ❌ 不能访问实例变量
}

这就是为什么 callbacks 必须是 static 的------onNewWant 是 static 方法,只能访问 static 变量。

五、宿主应用必须手动集成的原因

5.1 为什么不能自动化

平台 回调接收方式 是否需要手动集成
Android 独立的 CallbackActivity ❌ 只需配置 Manifest
iOS ASWebAuthenticationSession 自动处理 ❌ 不需要
OpenHarmony 复用 EntryAbility ✅ 必须手动写代码

5.2 Android 为什么不需要

Android 使用了一个独立的 CallbackActivity。这个 Activity 定义在插件的 AAR 包中,开发者只需要在 Manifest 中声明它。CallbackActivity 的代码由插件提供,不需要开发者写。

5.3 OpenHarmony 为什么不能用独立 Ability

复制代码
理论上可以创建一个独立的 CallbackAbility:
1. 浏览器重定向到 myapp://callback
2. 系统启动 CallbackAbility
3. CallbackAbility 获取 want.uri
4. CallbackAbility 把 uri 传给 FlutterWebAuthPlugin

问题:
- CallbackAbility 和 FlutterWebAuthPlugin 在不同的进程/实例中
- 无法直接访问 static callbacks
- 需要进程间通信,复杂度大增

💡 OpenHarmony 的 Ability 模型决定了必须复用 EntryAbility。因为 Flutter 引擎运行在 EntryAbility 中,插件的 static callbacks 也在这个进程中。深度链接必须回到同一个 Ability 才能访问 callbacks。

5.4 未来可能的改进

如果 Flutter-OHOS 框架提供了统一的深度链接分发机制(类似 Android 的 onNewIntent 自动转发),就不需要开发者手动集成了。但目前还没有这个能力。

六、集成代码的注意事项

6.1 import 路径

typescript 复制代码
import FlutterWebAuthPlugin from 'flutter_web_auth';

这个 import 路径是包名,不是文件路径。OpenHarmony 的模块系统会根据 oh-package.json5 中的 name 字段来解析。

6.2 不要忘记 super 调用

typescript 复制代码
// ✅ 正确
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  super.onNewWant(want, launchParam);  // 必须
  FlutterWebAuthPlugin.onNewWant(want);
}

// ❌ 错误:忘记 super
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  FlutterWebAuthPlugin.onNewWant(want);
  // 缺少 super.onNewWant → 可能导致 Flutter 路由异常
}

6.3 多个插件的深度链接处理

如果应用同时使用了多个需要深度链接的插件:

typescript 复制代码
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  super.onNewWant(want, launchParam);
  FlutterWebAuthPlugin.onNewWant(want);
  // AnotherDeepLinkPlugin.onNewWant(want);  // 其他插件
}

每个插件的 onNewWant 都应该检查 want.uri 是否与自己相关,不相关就静默忽略。

七、完整集成检查清单

7.1 代码检查

  • import FlutterWebAuthPlugin from 'flutter_web_auth'
  • import { AbilityConstant, Want } from '@kit.AbilityKit'
  • onNewWant 方法已重写
  • onNewWant 中调用了 super.onNewWant
  • onNewWant 中调用了 FlutterWebAuthPlugin.onNewWant(want)
  • onCreate 方法已重写(可选但推荐)
  • onCreate 中调用了 super.onCreate
  • onCreate 中调用了 FlutterWebAuthPlugin.onNewWant(want)

7.2 配置检查

  • module.json5 中 launchType 为 singleton
  • module.json5 中 skills 包含正确的 Scheme
  • module.json5 中 requestPermissions 包含 ohos.permission.INTERNET

7.3 测试验证

bash 复制代码
# 模拟深度链接
hdc shell aa start -a EntryAbility -b com.example.myapp -U "myapp://callback?code=test"

# 查看日志
hdc hilog | grep FlutterWebAuthPlugin

总结

本文详细讲解了 EntryAbility 的深度链接回调集成:

  1. onNewWant:App 在前台/后台时接收深度链接
  2. onCreate:App 冷启动时接收深度链接(但 callbacks 可能为空)
  3. static 方法设计:降低 EntryAbility 与插件的耦合
  4. 必须手动集成:OpenHarmony 的 Ability 模型决定的
  5. super 调用:不能忘记,否则影响其他功能

下一篇我们讲 openLink API------浏览器是怎么打开的。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

EntryAbility 生命周期

相关推荐
Geek_Vison9 小时前
保险APP已经用了Flutter,还能接入小程序吗?
flutter·小程序·uni-app·mpaas·小程序容器
FungLeo9 小时前
成为全栈·Flutter App 篇·go_router 与四 Tab App Shell:保留导航状态、深链和登录回跳
flutter·移动开发·成为全栈·go_router·路由设计·深链接
m0_738185829 小时前
Flutter 鸿蒙化实战:screen_protector 适配 OpenHarmony,防截屏/防泄露
flutter·华为·harmonyos·鸿蒙
梦想的颜色15 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭2 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白2 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫3 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘3 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185823 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙