Flutter三方库适配OpenHarmony【flutter_web_auth】— 深度链接(Deep Link)机制全解析
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net深度链接是 flutter_web_auth 在 OpenHarmony 上能工作的基础设施。没有深度链接,浏览器完成认证后就没办法把结果回传给 App。这篇把 OpenHarmony 的深度链接机制从底层讲清楚——Want 是什么、skills 怎么配、singleton 为什么必须、系
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
深度链接是 flutter_web_auth 在 OpenHarmony 上能工作的基础设施。没有深度链接,浏览器完成认证后就没办法把结果回传给 App。这篇把 OpenHarmony 的深度链接机制从底层讲清楚——Want 是什么、skills 怎么配、singleton 为什么必须、系统怎么匹配。
一、什么是深度链接
1.1 定义
深度链接(Deep Link)是一种通过 URL 直接打开 App 特定页面的技术。
普通链接:https://example.com/page → 在浏览器中打开
深度链接:myapp://callback?code=abc → 打开 myapp 应用
1.2 URL Scheme vs App Links

1.3 flutter_web_auth 使用的是 URL Scheme
FlutterWebAuth.authenticate(
url: "https://auth.example.com/authorize?redirect_uri=myapp://callback",
callbackUrlScheme: "myapp", // URL Scheme
);
💡 flutter_web_auth 使用 URL Scheme 而不是 App Links,因为 URL Scheme 配置简单,不需要域名验证。对于 OAuth 回调来说,URL Scheme 的安全性已经足够(配合 PKCE 使用)。
二、OpenHarmony 的 Want 机制
2.1 什么是 Want
Want 是 OpenHarmony 中 Ability 之间通信的载体,类似 Android 的 Intent。
import { Want } from '@kit.AbilityKit';
let want: Want = {
action: 'ohos.want.action.viewData',
uri: 'myapp://callback?code=abc123',
};
2.2 Want 的核心字段
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
| action | string | 操作类型 | ohos.want.action.viewData |
| uri | string | 目标 URI | myapp://callback?code=abc |
| bundleName | string | 目标应用包名 | com.example.myapp |
| abilityName | string | 目标 Ability 名 | EntryAbility |
| entities | string[] | 实体类别 | ["entity.system.browsable"] |
2.3 隐式 Want vs 显式 Want
// 显式 Want:指定目标应用和 Ability
let explicitWant: Want = {
bundleName: 'com.example.myapp',
abilityName: 'EntryAbility',
};
// 隐式 Want:通过 action + uri 匹配
let implicitWant: Want = {
action: 'ohos.want.action.viewData',
uri: 'myapp://callback',
};
深度链接使用的是隐式 Want——系统根据 URI 的 Scheme 找到匹配的 Ability。
三、module.json5 中的 skills 配置
3.1 宿主应用的配置
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
},
{
"entities": ["entity.system.browsable"],
"actions": ["ohos.want.action.viewData"],
"uris": [{ "scheme": "myapp" }]
}
],
"launchType": "singleton"
}
]
}
}
3.2 skills 三要素
| 要素 | 值 | 作用 |
|---|---|---|
| entities | entity.system.browsable |
表示可以从浏览器启动 |
| actions | ohos.want.action.viewData |
表示处理"查看数据"操作 |
| uris.scheme | myapp |
匹配 myapp:// 开头的 URI |
3.3 与 Android Intent Filter 的对应
| Android | OpenHarmony | 说明 |
|---|---|---|
<action android:name="android.intent.action.VIEW" /> |
"actions": ["ohos.want.action.viewData"] |
查看操作 |
<category android:name="android.intent.category.BROWSABLE" /> |
"entities": ["entity.system.browsable"] |
可从浏览器启动 |
<data android:scheme="myapp" /> |
"uris": [{"scheme": "myapp"}] |
Scheme 匹配 |
3.4 多 Scheme 配置
"uris": [
{ "scheme": "myapp" },
{ "scheme": "com.example.myapp" }
]
如果你的应用需要处理多个 Scheme(比如不同的 OAuth 提供商使用不同的回调 Scheme),可以在 uris 数组中添加多个。
四、singleton launchType 的必要性
4.1 三种启动模式
| 模式 | 行为 | 适用场景 |
|---|---|---|
| singleton | 只有一个实例,复用已有的 | flutter_web_auth 必须用 |
| multiton | 每次创建新实例 | 独立的页面 |
| specified | 指定实例 | 特殊场景 |
4.2 为什么必须是 singleton
场景:用户点击登录
1. App 在前台 → 打开浏览器(App 进入后台)
2. 用户在浏览器中完成认证
3. 浏览器重定向到 myapp://callback
4. 系统需要把 Want 传给 App
如果是 singleton:
→ 系统找到已有的 EntryAbility 实例
→ 调用 onNewWant(want)
→ 插件从 want.uri 中提取回调 URL ✅
如果是 multiton:
→ 系统创建新的 EntryAbility 实例
→ 调用 onCreate(want)
→ 新实例中没有 FlutterWebAuthPlugin 的 callbacks ❌
→ 认证结果丢失
4.3 singleton 的生命周期
首次启动:onCreate(want) → 创建实例
↓
深度链接唤起:onNewWant(want) → 复用实例
↓
再次深度链接:onNewWant(want) → 继续复用
↓
用户关闭:onDestroy() → 销毁实例
📌 singleton 模式下,深度链接通过 onNewWant 回调传递。这是 flutter_web_auth 能工作的前提条件。如果开发者把 launchType 改成 multiton,认证回调就会丢失。
五、系统级匹配流程
5.1 从浏览器到 App 的完整流程
1. 浏览器加载 https://auth.example.com/authorize
2. 用户完成认证
3. 服务器返回 302 重定向到 myapp://callback?code=abc123
4. 浏览器尝试打开 myapp://callback?code=abc123
5. 系统查找能处理 myapp:// 的 Ability
6. 匹配规则:
- action = ohos.want.action.viewData ✓
- entity = entity.system.browsable ✓
- uri.scheme = myapp ✓
7. 找到 EntryAbility(singleton 模式)
8. 调用 EntryAbility.onNewWant(want)
9. want.uri = "myapp://callback?code=abc123"
5.2 匹配优先级
如果多个 App 注册了相同的 Scheme:
| 情况 | 行为 |
|---|---|
| 只有一个 App 匹配 | 直接打开 |
| 多个 App 匹配 | 系统弹出选择器 |
| 没有 App 匹配 | 浏览器显示错误 |
5.3 Scheme 冲突的风险
App A 注册了 myapp://
App B 也注册了 myapp://
→ 用户需要选择打开哪个 App
→ 认证结果可能发到错误的 App
⚠️ Scheme 冲突是一个安全风险。建议使用反向域名格式的 Scheme,如
com.example.myapp,降低冲突概率。
六、深度链接调试
6.1 使用 hdc 测试深度链接
# 模拟深度链接唤起
hdc shell aa start -a EntryAbility -b com.example.myapp -U "myapp://callback?code=test123"
6.2 检查 skills 配置是否生效
# 查看应用的 Ability 信息
hdc shell bm dump -n com.example.myapp
6.3 常见调试问题
| 问题 | 原因 | 解决 |
|---|---|---|
| 深度链接不触发 | skills 配置错误 | 检查 entities/actions/uris |
| 打开了新实例 | launchType 不是 singleton | 修改为 singleton |
| onNewWant 不调用 | 没有在 EntryAbility 中重写 | 添加 onNewWant 方法 |
| want.uri 为空 | URI 格式不正确 | 检查 Scheme 拼写 |
七、与 Android 深度链接的对比
7.1 配置对比
<!-- Android: AndroidManifest.xml -->
<activity android:name=".CallbackActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" />
</intent-filter>
</activity>
// OpenHarmony: module.json5
{
"abilities": [{
"name": "EntryAbility",
"skills": [{
"entities": ["entity.system.browsable"],
"actions": ["ohos.want.action.viewData"],
"uris": [{ "scheme": "myapp" }]
}],
"launchType": "singleton"
}]
}
7.2 核心差异
| 维度 | Android | OpenHarmony |
|---|---|---|
| 配置格式 | XML | JSON5 |
| 回调接收者 | 独立 Activity | 复用 EntryAbility |
| 回调方法 | onCreate(intent) | onNewWant(want) |
| 启动模式 | singleTop/singleTask | singleton |
| 数据字段 | intent.data | want.uri |
总结
本文全面解析了 OpenHarmony 的深度链接机制:
- Want 机制:类似 Android Intent,通过 action + uri 匹配
- skills 配置:entities + actions + uris 三要素缺一不可
- singleton 必须:确保深度链接通过 onNewWant 传递给已有实例
- 系统匹配:浏览器重定向 → 系统匹配 Scheme → 唤起 App
- Scheme 冲突:建议使用反向域名格式降低风险
下一篇我们讲 EntryAbility 的集成代码——宿主应用需要做什么。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐

所有评论(0)