概述
在使用ArkTS与Web进行混合开发时,应用内的部分页面使用了前端相关能力进行了开发,再使用Web组件进行了页面加载,在这种场景下涉及到从Web加载的页面向其他页面跳转,以及从Web页面拉起应用。本文也将从这两方面介绍Web页面跳转以及拉起应用相关的知识:
Web页面与ArkTS页面互相跳转
Web页面跳转Web页面
开发者在做Hybrid App混合开发时,Web页面的跳转可以直接在前端侧使用HTML提供的a标签来进行跳转,修改href为跳转后的地址即可,参考代码如下:
<a href="www.example.com">跳转到其他页面</a>
ArkTS页面跳转Web页面
在HarmonyOS应用开发中,会有Web页面和ArkTS页面互相之间进行跳转的场景,例如列表页用了ArkTS进行开发,而详情页设计上只有简单的内容展示并没有复杂的逻辑操作,于是使用了Web开发并使用了ArkTS中的Web组件进行了加载,在这种场景下,从列表页跳转到详情页就是从ArkTS页面跳转到Web页面,在这种场景下,开发者只需要在ArkTS页面对应的事件回调函数中使用路由栈提供的跳转功能即可实现。
NavDestination() {
Column() {
Button($r('app.string.back_to_web_page'))
.width('100%')
.height(40)
.onClick(() => {
this.navPathStack.pushPath({ name: 'WebPage' });
})
}
// ...
}
.title('ArkTS页面')
Web页面跳转ArkTS页面
同样的,开发者也会有从Web页面跳转到ArkTS页面的场景,例如刚刚的场景中我希望返回到ArkTS页面,就是从Web页面跳转回ArkTS页面的场景,在这种场景下,实现步骤如下:
-
在HTML页面内使用a标签的href属性自定义跳转链接。
<a class="function_item" href="arkts://pages/toOriginPage">跳转到ArkTS页面</a>
说明
开发者可以根据业务场景自行定义href,此处的定义的href并不作为a标签跳转后的地址,而是会在ArkTS侧进行跳转拦截,当检测到该链接时执行自定义逻辑。
-
然后在Web页面中,需要在onLoadIntercept中进行跳转拦截,获取跳转的url,如果与自定义的跳转链接一致,那么可以使用路由栈进行原生的页面跳转。
Navigation(this.navPathStack) {
Column() {
Web({
src: $rawfile('index.html'),
controller: this.controller
})
.zoomAccess(false)
.onLoadIntercept((event) => {
const url: string = event.data.getRequestUrl();
if (url === 'arkts://pages/toOriginPage') {
this.navPathStack.pushPath({ name: 'OriginPage' });
}
// ...
})
}
}
Web页面拉起应用
Web页面拉起系统应用页面
从Web页面拉起系统应用界面,也是一个常见的场景,例如开发者有发布图片的需求,而且图片上传的界面在前端界面已经有了实现并且做了多端适配,现在希望复用原有的界面,但是具体的图片选择的逻辑以及上传的逻辑希望修改成ArkTS侧的实现。实现步骤如下:
-
在Web页面内配置跳转的链接地址。此处使用a标签并不意味着上传的HTML元素就是a标签,而是以它为例,理论上开发者可以用任何HTML元素绑定onClick事件,通过设置window.location.href属性进行页面跳转。
<a class="function_item" href="photo://pages/selectPhoto">拉起系统应用</a>
-
接着使用ArkTS侧提供的照片选择Picker进行图片的选择以及后续逻辑的开发。
Navigation(this.navPathStack) {
Column() {
Web({
src: $rawfile('index3.html'),
controller: this.controller
})
.zoomAccess(false)
.onLoadIntercept((event) => {
const url: string = event.data.getRequestUrl();
if (url === 'photo://pages/selectPhoto') {
const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
photoSelectOptions.maxSelectNumber = 5; // 选择媒体文件的最大数目
let uris: Array<string> = [];
const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
photoViewPicker.select(photoSelectOptions)
.then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
uris = photoSelectResult.photoUris;
console.info('photoViewPicker.select to file succeed and uris are:' + uris);
})
.catch((err: BusinessError) => {
console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
}
return url !== 'resource://rawfile/index3.html';
})
}
}
.hideTitleBar(true)
.navDestination(this.PageMap)
Web页面拉起三方应用
开发者在HarmonyOS应用内使用了Web页面做了部分页面的实现,同时出于推广,或者需要在其他应用内处理一些逻辑等目的,需要拉起其他的三方应用,例如跳转到支付应用进行支付,在这些场景下,就需要用到拉起三方应用的相关知识,首先在实现方案上,拉起三方应用建议使用如下两种方案:
- 使用[Deep Linking]实现应用拉起。
- 使用[App Linking]实现应用拉起。
方案1:使用Deep Linking。
- 在目标方配置module.json5文件,保证entities中包含entity.system.browsable、actions中包含ohos.want.action.viewData,最后再配置uris,用户可以自定义scheme,host,port以及path。
{
"module": {
// ...
"abilities": [
{
// ...
"skills": [
{
"entities": [
// ...
"entity.system.browsable"
],
"actions": [
// ...
"ohos.want.action.viewData"
],
"uris": [
{
"scheme": "appScheme", // scheme可以自定义
"host": "www.test.com", // host须配置关联的域名
"port": "80", // port可选
"path": "path1" // path可选,为了避免匹配到多个应用,建议配置该字段
}
]
}
],
}
],
// ...
}
}
- 在调用方的module.json5文件中配置[querySchemes],标识允许当前应用进行跳转查询的URL schemes。
"querySchemes": [
"appScheme"
],
-
根据目标方的uris配置拼凑出完整的link地址,拼接方式为:scheme://host:port/path
const link: string = "appScheme://www.test.com:80/path1";
-
通过[canOpenLink]接口判断link是否可以打开,如不能打开链接开发者可以自定义响应逻辑,此处直接返回。
if (!bundleManager.canOpenLink(link)) {
return;
}
- 配置拉起时的启动参数openLinkOptions,在该配置中可以进行参数传递以及配置appLinkingOnly属性。代码参考如下:
Navigation(this.navPathStack) {
Column() {
Web({
src: $rawfile('index2.html'),
controller: this.controller
})
.zoomAccess(false)
.onLoadIntercept((event) => {
const url: string = event.data.getRequestUrl();
if (url === 'third-party://pages/toThirdApp') {
const link: string = "appScheme://www.test.com:80/path1";
if (!bundleManager.canOpenLink(link)) {
return;
}
const openLinkOptions: OpenLinkOptions = {
appLinkingOnly: false,
parameters: {
name: 'test'
}
};
this.context.openLink(link, openLinkOptions).then(() => {
console.info('open link success.');
}).catch((err: BusinessError) => {
console.error(`open link failed. Code is ${err.code}, message is ${err.message}`);
})
}
return url !== 'resource://rawfile/index2.html';
})
}
}
方案2:当开发者希望无论应用是否已安装,用户都可以访问到链接对应的内容,当应用安装时优先打开应用去呈现内容;当应用未安装时,则打开浏览器呈现Web版的内容,就可以使用App Linking的方式
总结:Deep Linking适用于需要在已安装的应用之间进行跳转,实现相对简单,但当无应用匹配时用户体验不佳。而App Linking适用于社交分享、广告引流等需要外部链接访问应用的场景,以及对安全性和用户体验要求较高的场景。AppLinking在Deep Linking的基础上增加了域名校验,提高了链接的安全性和可靠性,且无论应用是否安装,用户都能访问内容,缺点是实现相对复杂。