本章节主要介绍如何通过应用链接跳转的方式拉起指定应用。
按照应用链接的scheme以及校验机制的不同,可以分为Deep Linking与App Linking两种方式。
Deep Linking:是一种通过链接跳转至应用特定页面的技术,其特点是支持开发者定义任意形式的scheme。由于缺乏域名校验机制,容易被其他应用所仿冒。
App Linking:其限定了scheme必须为https,同时通过增加域名校验机制,可以从已匹配到的应用中筛选过滤出目标应用,消除应用查询和定位中产生的歧义,直达受信的目标应用。
相比Deep Linking,App Linking具有更高的安全性和可靠性,用户体验更佳。推荐开发者将App Linking作为首选方案。
| 类型 | App Linking(推荐) | Deep Linking |
|---|---|---|
| 实现方案 | 目标应用需要在module.json5中声明应用链接;同时需要向系统注册域名并通过域名认证。 | 目标应用需要在module.json5中声明应用链接。 |
| 链接格式 | scheme必须为https。 | scheme可以自定义。通常不为https、http、file,否则会拉起默认的系统浏览器。 |
| 是否可用于分享或直接在网页中访问 | 可以 | 不可以,需在代码中调用。 |
| 是否可以直接拉起目标应用 | 可以 | 可以,但不推荐使用,存在被仿冒风险。 |
Deep Linking与App Linking均可以使用openLink()接口实现,不同条件下的跳转效果如下。
该接口中的appLinkingOnly字段表示是否必须以App Linking的方式启动UIAbility,默认为false。appLinkingOnly为true一般只用于浏览器等应用。
| 应用链接类型 | App Linking(推荐) | Deep Linking |
|---|---|---|
| appLinkingOnly为false且目标应用已安装 | 直接跳转打开目标应用。 | 跳转目标应用(如果有多个符合条件的应用时,展示应用选择弹框)。 |
| appLinkingOnly为false且目标应用未安装 | 跳转默认浏览器打开网页。 | 返回失败,系统不跳转,由应用自行处理;当前会展示“链接无法打开”弹框。 |
| appLinkingOnly为true且目标应用已安装 | 直接跳转打开目标应用。 | 返回失败,系统不跳转,由应用自行处理。 |
| appLinkingOnly为true且目标应用未安装 | 返回失败,系统不跳转由应用自行处理。 | 返回失败,系统不跳转,由应用自行处理。 |
通过App Linking方式拉起指定应用的示意图如下:

通过Deep Linking方式拉起应用时,如果存在多个符合条件的应用,需要用户选择后方可跳转到指定应用。示意图如下:

通过startAbility方式或Deep Linking方式拉起其他应用的UIAbility时,系统会弹出“是否允许跳转”的确认弹框,由用户进行选择。可通过CompletionHandler感知用户的选择结果。
通过openLink或startAbility拉起其他应用时,为了防止应用的恶意跳转,系统会弹出“是否允许跳转”的确认弹框,由用户进行确认。不支持开发者取消该弹框。
“是否允许跳转”的确认弹框实际显示的提示语由系统定义,比如“xx想要拉起xx”,此处仅为举例。
当通过openLink或startAbility隐式启动其他应用时,如果没有找到匹配的应用,系统会弹框提示“暂无可用打开方式”。
openLink方式启动其他应用:API version 21版本之前,不支持取消弹框提示。从API version 21版本开始,可以将OpenLinkOptions中的hideFailureTipDialog字段设置为true,取消弹框提示。
示例如下:
import { common, OpenLinkOptions, wantConstant, CompletionHandler, bundleManager } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN = 0xeeee;
const TAG: string = '[openLinkDemo]';
@Entry
@Component
struct Index {
@State message: string = 'I am caller';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button('start browser', { type: ButtonType.Capsule, stateEffect: true })
.width('87%')
.height('5%')
.margin({ bottom: '12vp' })
.onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
let link: string = 'https://www.example.com';
let completionHandler: CompletionHandler = {
onRequestSuccess: (elementName: bundleManager.ElementName, message: string): void => {
console.info(`${elementName.bundleName}-${elementName.moduleName}-${elementName.abilityName} start succeeded: ${message}`);
},
onRequestFailure: (elementName: bundleManager.ElementName, message: string): void => {
console.error(`${elementName.bundleName}-${elementName.moduleName}-${elementName.abilityName} start failed: ${message}`);
}
};
let openLinkOptions: OpenLinkOptions = {
appLinkingOnly: false,
// hideFailureTipDialog字段需要在appLinkingOnly字段是false时才生效
hideFailureTipDialog: true,
parameters: {
[wantConstant.Params.CONTENT_TITLE_KEY]: 'contentTitle',
keyString: 'str',
keyNumber: 200,
keyBool: false,
keyObj: {
keyObjKey: 'objValue',
}
},
completionHandler: completionHandler
};
try {
context.openLink(
link,
openLinkOptions,
(err, result) => {
hilog.error(DOMAIN, TAG, `openLink callback error.code: ${JSON.stringify(err)}`);
hilog.info(DOMAIN, TAG, `openLink callback result: ${JSON.stringify(result.resultCode)}`);
hilog.info(DOMAIN, TAG, `openLink callback result data: ${JSON.stringify(result.want)}`);
}
).then(() => {
hilog.info(DOMAIN, TAG, `open link success.`);
}).catch((err: BusinessError) => {
hilog.error(DOMAIN, TAG, `open link failed, errCode: ${JSON.stringify(err.code)}`);
});
} catch (e) {
hilog.error(DOMAIN, TAG, `open link failed, errCode: ${JSON.stringify(e.code)}`);
}
})
}
.width('100%')
}
.height('100%')
}
} startAbility隐式启动其他应用:可以通过将Want中的flags字段设置为FLAG_START_WITHOUT_TIPS,取消弹框提示。
示例如下:
import { common, Want, wantConstant } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
private context = this.getUIContext().getHostContext() as common. UIAbilityContext;
build() {
Column() {
// ...
List({ initialIndex: 0 }) {
ListItem() {
Row() {
// ...
}
.onClick(() => {
// context为UIAbility对象的成员
let wantInfo: Want = {
deviceId: '', // deviceId为空表示本设备
action: 'xxxx', // 隐式启动
flags: wantConstant.Flags.FLAG_START_WITHOUT_TIPS,
};
// context为调用方UIAbility的UIAbilityContext
this.context.startAbility(wantInfo).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');
}).catch((error: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');
});
})
}
// ...
}
// ...
}
// ...
}
}