在鸿蒙应用开发中,应用间跳转是常见需求,比如点击分享链接直接打开商品详情页。鸿蒙提供了两种主流方案:Deep Linking 和 App Linking。本文将聚焦 Deep Linking,从被拉端配置、链接解析、拉起方实现到常见踩坑记录,手把手带你完成从零到一的全流程。
Deep Linking 基于系统隐式 Want 的 URI 匹配机制:拉起方调用 openLink 或 startAbility 传一个 URI 给系统,系统扫描所有已安装应用,找到能处理该 URI 的应用并拉起。如果多个应用都能处理,系统会弹出选择框让用户决定。这种方式的优点是配置少、门槛低,但安全性完全靠开发者自己把控。
一、被拉端配置:module.json5 中声明 skills
要让你的应用能被其他App拉起,首先在 module.json5 的 abilities 中配置 skills。关键规则:
- 不能写在默认的入口 skill(即 entity.system.home)中,必须新建一个独立的 skill 对象。
- 多个跳转场景(如商品页、店铺页)需建多个 skill,混在一起会导致配置失效。
- actions 字段不能为空,否则匹配失败。
- scheme 不能以 ohos 开头,也不建议使用 https、http、file、store 等系统保留 scheme。
- uris 中可以配置 scheme、host、path、pathStartWith、pathRegex 来做精细匹配。
例如:- "skills": [
- {
- "entities": ["entity.system.home"],
- "actions": ["ohos.want.action.home"]
- },
- {
- "actions": ["ohos.want.action.viewData"],
- "uris": [
- {
- "scheme": "myapp",
- "host": "www.example.com",
- "pathStartWith": "/goods/"
- }
- ]
- }
- ]
复制代码
注意:目标 Ability 的 exported 属性必须设为 true,否则其他应用无法拉起它。这个坑不少人踩过。
二、被拉端解析链接参数
在被拉起的 Ability 中,需要在 onCreate(冷启动)和 onNewWant(热启动)两个回调里解析 URI 参数。冷启动指应用进程被杀死后启动,走 onCreate;热启动指应用已在后台,切到前台时走 onNewWant。两个回调都要处理,否则用户在后台点击链接会丢失参数。
示例代码:- export default class EntryAbility extends UIAbility {
- onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
- this.handleLink(want);
- }
- onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
- this.handleLink(want);
- }
- private handleLink(want: Want): void {
- let uri = want?.uri;
- if (uri) {
- // 解析 uri 中的参数,例如 goodsId、from 等
- // 存入 AppStorage 或全局变量供页面使用
- }
- }
- }
复制代码
推荐使用 url.URL.parseURL 解析 URI,获取 params 中的 query 参数。
三、拉起方实现跳转
拉起方有三种实现方式:
1. openLink(推荐,API 12+)
调用 context.openLink(link, { appLinkingOnly: false }),将 appLinkingOnly 设为 false 表示使用 Deep Linking 而非 App Linking。该方法返回 Promise,可捕获失败情况。
2. startAbility(隐式 Want)
构造 Want 对象,填入 uri 后调用 context.startAbility(want)。该方法与 openLink 的区别在于缺少 appLinkingOnly 参数控制,且错误处理不如 openLink 直观。
3. Web 组件中跳转
如果应用内嵌了 Web 页面,需要在 onLoadIntercept 回调中拦截自定义 scheme 的链接,调用 openLink 跳转,并 return true 阻止 Web 组件继续加载。
跳转前建议使用 canOpenLink 检查设备上是否有应用能处理该链接,返回 false 时做降级处理(如打开浏览器或弹提示)。
四、多场景配置技巧
如果你的 App 有多个跳转场景,可以在 module.json5 中为每个场景建一个 skill,通过 pathStartWith 或 path 区分。例如商品页用 /goods/,店铺页用 /shop/,活动页用 /activity/。每个 skill 也可单独配置 entities 做更精细控制。
五、踩坑记录(重点)
坑1:exported 忘了设为 true
目标 App 的 Ability 中 exported 默认是 false,导致其他应用无法拉起。排查时务必检查模块配置。
坑2:skills 写到了默认入口 skill 里
把 Deep Linking 的 skills 与 entity.system.home 混在一起会导致入口异常或跳转失效。必须分两个独立的 skill 对象。
坑3:scheme 冲突导致弹选择框
使用过于通用的 scheme(如 link、app、go)容易与其他 App 冲突。建议用公司名+业务名拼接,如 mycompany_shop。如果实在冲突且无法改 scheme,拉起方可用显式 Want 直接指定目标应用的 bundleName 和 abilityName,绕过系统匹配。
坑4:热启动收不到链接参数
只处理了 onCreate 而忽略了 onNewWant,导致应用已在后台时点击链接参数丢失。务必两个回调都处理。
坑5:使用系统保留 scheme
不要使用 https、http、file、store、filemanager、hww 等保留 scheme,否则系统会优先交给浏览器等系统应用处理,不会激活你的 Deep Linking。
坑6:actions 为空导致匹配失败
skills 中必须至少配置一个 action(如 ohos.want.action.viewData),仅配 uris 不配 actions 会导致永远不会被匹配。
六、总结
Deep Linking 是鸿蒙应用间跳转最基础的方式,配置少、上手快,但局限也很明显:scheme 冲突是最大隐患,安全性完全依赖开发者,且不适合对外暴露的场景(推荐使用 App Linking)。建议在内部 App 跳转、快速验证阶段使用 Deep Linking。如果涉及社交分享或跨公司对接,应选择 App Linking。
后续将撰文介绍 App Linking 的配置与使用,敬请关注。 |