1# 使用Deep Linking实现应用间跳转
2
3采用Deep Linking进行跳转时,系统会根据接口中传入的uri信息,在本地已安装的应用中寻找到符合条件的应用并进行拉起。当匹配到多个应用时,会拉起应用选择框。
4
5## 实现原理
6
7Deep Linking基于隐式Want匹配机制中的uri匹配来查询、拉起目标应用。隐式Want的uri匹配规则详见[uri匹配规则](explicit-implicit-want-mappings.md#uri匹配规则)。
8
9
10## 目标应用操作指导
11
12### 配置module.json5文件
13
14为了能够支持被其他应用访问,目标应用需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中配置[skills标签](../quick-start/module-configuration-file.md#skills标签)。其中,scheme的取值支持自定义,可以定义为任意不包含特殊字符、非`ohos`开头的字符串。
15
16> **说明:**
17>
18> Deep Linking中的scheme取值通常不为https、http、file,否则会拉起默认的系统浏览器。
19
20
21配置示例如下:
22
23```json
24{
25  "module": {
26    // ...
27    "abilities": [
28      {
29        // ...
30        "skills": [
31          {
32            "actions": [
33              // actions不能为空,actions为空会造成目标方匹配失败
34              "ohos.want.action.viewData"
35            ],
36            "uris": [
37              {
38                // scheme必选,可以自定义,以link为例,需要替换为实际的scheme
39                "scheme": "link",
40                // host必选,配置待匹配的域名
41                "host": "www.example.com"
42              }
43            ]
44          }
45        ]
46      }
47    ]
48  }
49}
50```
51
52### 获取并解析拉起方传入的应用链接
53
54在目标应用的UIAbility的onCreate()或者onNewWant()生命周期回调中,获取、解析拉起方传入的应用链接。
55
56```ts
57// 以EntryAbility.ets为例
58import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
59import { url } from '@kit.ArkTS';
60
61export default class EntryAbility extends UIAbility {
62  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
63    // 从want中获取传入的链接信息。
64    // 如传入的url为:link://www.example.com/programs?action=showall
65    let uri = want?.uri;
66    if (uri) {
67      // 从链接中解析query参数,拿到参数后,开发者可根据自己的业务需求进行后续的处理。
68      let urlObject = url.URL.parseURL(want?.uri);
69      let action = urlObject.params.get('action');
70      // 例如,当action为showall时,展示所有的节目。
71      if (action === "showall") {
72         // ...
73      }
74    }
75  }
76}
77```
78
79## 拉起方应用实现应用跳转
80
81下面通过三个案例,分别介绍如何使用[openLink()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextopenlink12)与[startAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability)接口实现应用跳转,以及如何在[Web组件](../reference/apis-arkweb/ts-basic-components-web.md)中实现应用跳转。
82
83### 使用openLink实现应用跳转
84
85在[openLink](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextopenlink12)接口的link字段中传入目标应用的URL信息,并将options字段中的`appLinkingOnly`配置为`false`。
86
87
88示例代码如下:
89
90```ts
91import { common, OpenLinkOptions } from '@kit.AbilityKit';
92import { BusinessError } from '@kit.BasicServicesKit';
93import { hilog } from '@kit.PerformanceAnalysisKit';
94
95const TAG: string = '[UIAbilityComponentsOpenLink]';
96const DOMAIN_NUMBER: number = 0xFF00;
97
98@Entry
99@Component
100struct Index {
101  build() {
102    Button('start link', { type: ButtonType.Capsule, stateEffect: true })
103      .width('87%')
104      .height('5%')
105      .margin({ bottom: '12vp' })
106      .onClick(() => {
107        let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
108        let link: string = "link://www.example.com";
109        let openLinkOptions: OpenLinkOptions = {
110          appLinkingOnly: false
111        };
112
113        try {
114          context.openLink(link, openLinkOptions)
115            .then(() => {
116              hilog.info(DOMAIN_NUMBER, TAG, 'open link success.');
117            }).catch((err: BusinessError) => {
118              hilog.error(DOMAIN_NUMBER, TAG, `open link failed. Code is ${err.code}, message is ${err.message}`);
119            });
120        } catch (paramError) {
121          hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. Code is ${paramError.code}, message is ${paramError.message}`);
122        }
123      })
124  }
125}
126```
127
128### 使用startAbility实现应用跳转
129
130[startAbility](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability)接口是将应用链接放入want中,通过调用[隐式want匹配](explicit-implicit-want-mappings.md#隐式want匹配原理)的方法触发应用跳转。通过[startAbility](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability)接口启动时,还需要调用方传入待匹配的action和entity。
131
132
133示例代码如下:
134
135```ts
136import { common, Want } from '@kit.AbilityKit';
137import { BusinessError } from '@kit.BasicServicesKit';
138import { hilog } from '@kit.PerformanceAnalysisKit';
139
140const TAG: string = '[UIAbilityComponentsOpenLink]';
141const DOMAIN_NUMBER: number = 0xFF00;
142
143@Entry
144@Component
145struct Index {
146  build() {
147    Button('start ability', { type: ButtonType.Capsule, stateEffect: true })
148      .width('87%')
149      .height('5%')
150      .margin({ bottom: '12vp' })
151      .onClick(() => {
152        let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
153        let want: Want = {
154            uri: "link://www.example.com"
155        };
156
157        try {
158          context.startAbility(want).then(() => {
159            hilog.info(DOMAIN_NUMBER, TAG, 'start ability success.');
160          }).catch((err: BusinessError) => {
161            hilog.error(DOMAIN_NUMBER, TAG, `start ability failed. Code is ${err.code}, message is ${err.message}`);
162          });
163        } catch (paramError) {
164          hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${paramError.code}, message is ${paramError.message}`);
165        }
166      })
167  }
168}
169```
170
171### 使用Web组件实现应用跳转
172
173Web组件需要跳转DeepLink链接应用时,可通过拦截回调[onLoadIntercept](../reference/apis-arkweb/ts-basic-components-web.md#onloadintercept10)中对定义的事件进行处理,实现应用跳转。
174
175示例代码如下:
176
177```ts
178// index.ets
179import { webview } from '@kit.ArkWeb';
180import { BusinessError } from '@kit.BasicServicesKit';
181import { common } from '@kit.AbilityKit';
182
183@Entry
184@Component
185struct WebComponent {
186  controller: webview.WebviewController = new webview.WebviewController();
187
188  build() {
189    Column() {
190      Web({ src: $rawfile('index.html'), controller: this.controller })
191        .onLoadIntercept((event) => {
192          const url: string = event.data.getRequestUrl();
193          if (url === 'link://www.example.com') {
194            (getContext() as common.UIAbilityContext).openLink(url)
195              .then(() => {
196                console.log('openLink success');
197              }).catch((err: BusinessError) => {
198                console.error('openLink failed, err:' + JSON.stringify(err));
199              });
200            return true;
201          }
202          // 返回true表示阻止此次加载,否则允许此次加载
203          return false;
204        })
205    }
206  }
207}
208```
209
210前端页面代码:
211```html
212// index.html
213<!DOCTYPE html>
214<html>
215<head>
216    <meta charset="UTF-8">
217</head>
218<body>
219<h1>Hello World</h1>
220<!--方式一、通过绑定事件window.open方法实现跳转-->
221<button class="doOpenLink" onclick="doOpenLink()">跳转其他应用一</button>
222<!--方式二、通过超链接实现跳转-->
223<a href="link://www.example.com">跳转其他应用二</a>
224</body>
225</html>
226<script>
227    function doOpenLink() {
228        window.open("link://www.example.com")
229    }
230</script>
231```