鸿蒙 App Linking实现:通过应用链接拉起指定应用(二)
使用App Linking应用链接进行跳转时,系统会根据接口传入的uri信息(HTTPS链接)将用户引导至目标应用中的特定内容,无论应用是否已安装,用户都可以访问到链接对应的内容,跳转体验相比Deep Linking方式更加顺畅。例如:当使用App Linking应用链接接入“扫码直达”服务后,用户可通过控制中心扫一扫这类系统级扫码入口,扫描应用的二维码、条形码并跳转到应用对应服务页,实现一步直达
App Linking相比Deep Linking增加了域名校验环节,使链接更加安全可靠。无论应用是否已安装,用户都可以访问到链接对应的内容,跳转体验更加顺畅。
一、场景介绍
使用App Linking应用链接进行跳转时,系统会根据接口传入的uri信息(HTTPS链接)将用户引导至目标应用中的特定内容,无论应用是否已安装,用户都可以访问到链接对应的内容,跳转体验相比Deep Linking方式更加顺畅。
例如:当使用App Linking应用链接接入“扫码直达”服务后,用户可通过控制中心扫一扫这类系统级扫码入口,扫描应用的二维码、条形码并跳转到应用对应服务页,实现一步直达的体验。
说明:该能力目前仅适用于5.0.0(12)及以上版本的HarmonyOS应用。
二、原理机制
2.1 App Linking vs Deep Linking
App Linking在Deep Linking基础上增加了域名校验环节,通过域名校验,可帮助用户消除歧义,识别合法归属于域名的应用,使链接更加安全可靠。
2.2 呈现方式
App Linking对于同一HTTPS网址,有应用和网页两种内容的呈现方式:
| 情况 | 行为 |
|---|---|
| 应用已安装 | 优先打开应用去呈现内容 |
| 应用未安装 | 打开浏览器呈现Web版内容 |
三、支持版本
| 设备类型 | 支持版本 |
|---|---|
| Phone | 支持 |
| PC/2in1 | 支持 |
| Tablet | 支持 |
| TV | 5.1.1(19)开始支持 |
四、前提条件
五、开发流程
| 角色 | 操作步骤 |
|---|---|
| 云端开发 | 开通App Linking服务 |
| 云端开发 | 建立域名与应用关联关系 |
| 云端开发 | 在AGC为应用创建关联的网址域名 |
| 客户端开发 | 在module.json5中配置关联的网址域名 |
| 客户端开发 | 处理传入的链接 |
| 前端开发 | 开发链接对应的H5网页(应用未安装时呈现Web版内容) |
| 客户端开发 | 验证应用被拉起效果 |
六、配置应用链接能力
6.1 建立域名与应用关联关系
在开发者的网站域名服务器上做如下配置,后续在AGC创建关联网址域名时,AGC会通过此文件确认哪些应用才是合法归属于此域名的。
步骤1:创建域名配置文件applinking.json
{
"applinking": {
"apps": [
{
"appIdentifier": "1234567",
"index": 1
},
{
"appIdentifier": "7654321",
"index": 2
}
]
}
}
参数:
| 参数 | 必选 | 类型 | 说明 |
|---|---|---|---|
appIdentifier |
M | String | 创建应用时生成的APP ID |
index |
O | Integer | 优先级(-100~100),值越大优先级越高(起始版本:6.1.0(23)) |
说明:同一个网站域名可以关联多个应用,只需要在"apps"列表里放置多个"appIdentifier"元素即可。
index优先级规则:
| 情况 | 行为 |
|---|---|
| 匹配到多个应用,都未配置index | 拉起所有匹配的应用,弹出对话框让用户选择 |
| 部分或全部配置了index | 拉起index值最大的应用;多个index值最大时,拉起这些应用并弹窗选择 |
步骤2:上传配置文件
将applinking.json配置文件放在域名服务器的固定目录下:
https://domain.name/.well-known/applinking.json
示例:服务器域名为www.example.com,则必须将applinking.json文件放在:
https://www.example.com/.well-known/applinking.json
6.2 在AGC为应用创建关联的网址域名
-
点击"开发与服务"
-
在项目列表中点击HarmonyOS应用所在的项目
-
左侧导航栏选择"增长 → App Linking → 应用链接",点击"创建"
填写域名:填写建立域名与应用关联关系的网址域名,例如:https://www.example.com
注意:必须输入精确的域名,不可输入包含特殊字符的模糊网址,不可以在域名后面添加/。
发布状态:
| 状态 | 说明 |
|---|---|
| 发布成功 | 配置文件中存在本项目中的应用 |
| 发布中 | 还在校验中 |
| 发布失败 | 配置文件中没有包含任何本项目中的应用 |
说明:如果距离上次更新超过24小时,系统会去域名服务器上重新获取配置文件进行交集校验。
6.3 在module.json5中配置关联的网址域名
在应用的module.json5文件中进行如下配置。
配置要求:
| 配置项 | 要求 |
|---|---|
entities |
必须包含"entity.system.browsable" |
actions |
必须包含"ohos.want.action.viewData" |
uris |
必须包含scheme为"https"且host为域名地址的元素 |
domainVerify |
设置为true,开启域名校验开关 |
exported |
设置为true |
注意:skills标签下默认包含一个skill对象用于标识应用入口,应用跳转链接不能在第一个skill对象中配置,需要创建独立的skill对象。如果存在多个跳转场景,需要在skills标签下创建不同的skill对象。
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"exported": true,
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["ohos.want.action.home"]
},
{
"entities": ["entity.system.browsable"],
"actions": ["ohos.want.action.viewData"],
"uris": [
{
"scheme": "https",
"host": "www.example.com",
"path": "path1"
}
],
"domainVerify": true
}
]
}
]
}
}
6.4 处理传入的链接
在应用的Ability(如EntryAbility)的onCreate()或者onNewWant()生命周期回调中添加代码处理传入的链接。
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { url } from '@kit.ArkTS';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let uri = want?.uri;
if (uri) {
try {
let urlObject = url.URL.parseURL(want?.uri);
let action = urlObject.params.get('action');
if (action === "showall") {
// 处理业务逻辑
}
} catch (error) {
hilog.error(0x0000, 'testTag', `Failed to parse url.`);
}
}
}
}
七、验证应用被拉起效果
7.1 签名要求
必须使用手动签名,不能使用自动签名。
7.2 验证方式
| 方式 | 说明 |
|---|---|
| 点击链接验证 | 将链接存入备忘录,点击验证 |
| openLink接口拉起 | 通过UIAbilityContext.openLink()接口拉起 |
| 系统浏览器/ArkWeb拉起 | 在系统浏览器或ArkWeb网页上点击链接 |
| 系统级扫码入口拉起 | 扫描二维码验证(如美团扫码直达) |
7.3 通过openLink接口拉起示例
GlobalContext.ets:
import { common } from '@kit.AbilityKit';
export class GlobalContext {
private static context: common.UIAbilityContext;
public static initContext(context: common.UIAbilityContext): void {
GlobalContext.context = context;
}
public static getContext(): common.UIAbilityContext {
return GlobalContext.context;
}
}
Index.ets:
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { GlobalContext } from '../common/GlobalContext';
@Entry
@Component
struct Index {
build() {
Button('start link')
.onClick(() => {
let context = GlobalContext.getContext();
let link: string = "https://www.example.com/programs?action=showall";
context.openLink(link, { appLinkingOnly: true })
.then(() => {
hilog.info(0x0000, 'testTag', `Succeeded in opening link.`);
})
.catch((error: BusinessError) => {
hilog.error(0x0000, 'testTag', `Failed to open link, code: ${error.code}, message: ${error.message}`);
});
})
}
}
更多推荐



所有评论(0)