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