在实际开发过程中,会遇到需要外跳其他三方应用的情况,我们会用到App Linking和Deep Linking。这里讲解Deep Linking 跳转实现方式。

跳转逻辑

采用Deep Linking进行跳转时,系统会根据接口中传入的uri信息,在本地已安装的应用中寻找到符合条件的应用并进行拉起。当匹配到多个应用时,会拉起应用选择框。

跳转原理

Deep Linking基于隐式Want匹配机制中的uri匹配来查询、拉起目标应用。

跳转条件

目标应用(需要跳转的三方应用)需要在module.json5配置文件中配置skills标。这里做演示,获取目标应用信息方式,请查看<应用间跳转 - 判断应用是否可访问>

{
  "module": {
    "abilities": [
      {
        "skills": [
        // entities和actions是可以缺省的
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "ohos.want.action.home"
            ]
          },
          {
            "actions": [
              // actions不能为空,actions为空会造成目标方匹配失败。
              "ohos.want.action.viewData"
            ],
            "uris": [
              {
                // scheme必选,可以自定义,以link为例,需要替换为实际的scheme
                "scheme": "link",
                "host": "www.example.com""port":"80",
                "path":"path",
                "type": "text/*",
                "linkFeature": "Login"
              }
            ]
          } // 新增一个skill对象,用于跳转场景。如果存在多个跳转场景,需配置多个skill对象。
        ]
      },
    ],
  }
}

skills:
1、actions:标识能够接收的Action值集合,取值通常为系统预定义的action值,也允许自定义。一个skill中不建议配置多个action,否则可能导致无法匹配预期场景。
2、entities:标识能够接收的Entity值的集合。一个skill中不建议配置多个entity,否则可能导致无法匹配预期场景。
3、uris:标识与Want中URI(Uniform Resource Identifier)相匹配的集合。
4、permissions:标识当前UIAbility或ExtensionAbility组件的权限信息。其他应用访问该组件时,需要申请相应的权限。一个数组元素为一个权限名称,不超过255字节。
5、domainVerify:标识是否开启域名校验。- true:表示开启域名校验。- false:表示不开启域名校验。

uris:
1、scheme:标识URI的协议名部分,常见的有http、https、file、ftp等。(从API 18开始,该标签在参与隐式Want匹配时不区分大小写。)uris中仅配置type时可以缺省,缺省值为空,否则不可缺省。可以理解为简单实用跳转功能时,这个是必须的,以下都是可以缺省的。
2、host:标识URI的主机地址部分,该标签只有当scheme配置时才生效。
3、port:标识URI的端口部分。(如http默认端口为80,https默认端口是443,ftp默认端口是21。该标签只有当scheme和host都配置时才生效。)
4、linkFeature:标识URI提供的功能类型(如文件打开、分享、导航等),用于实现应用间跳转。取值为长度不超过127字节的字符串,不支持中文。同一Bundle中声明的linkFeature数量不能超过150个。
5、path | pathStartWith | pathRegex:标识URI的路径部分,path、pathStartWith和pathRegex配置时三选一。path标识URI与want中的路径部分全匹配,pathStartWith标识URI与want中的路径部分允许前缀匹配,pathRegex标识URI与want中的路径部分允许正则匹配。该标签只有当scheme和host都配置时才生效。
6、type:标识与Want相匹配的数据类型,使用MIME(Multipurpose Internet Mail Extensions)类型规范和UniformDataType类型规范。可以与scheme同时配置,也可以单独配置。
7、utd:标识与Want相匹配的标准化数据类型,适用于分享等场景。
8、maxFileSupported:对于指定类型的文件,标识一次能接收或打开的最大数量,适用于分享等场景,需要与utd配合使用。

拉起方应用实现应用跳转

1、使用openLink实现
在openLink接口的link字段中传入目标应用的URL信息,并将options字段中的appLinkingOnly配置为false。

let link: string = 'link://www.example.com'; // 此处为实际应用链接
            let openLinkOptions: OpenLinkOptions = {
              appLinkingOnly: false
            };

            try {
              context.openLink(link, openLinkOptions)
                .then(() => {
                  hilog.info(DOMAIN_NUMBER, TAG, 'openLink success.');
                }).catch((err: BusinessError) => {
                hilog.error(DOMAIN_NUMBER, TAG, `openLink failed. Code is ${err.code}, message is ${err.message}`);
              });
            } catch (paramError) {
              hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. Code is ${paramError.code}, message is ${paramError.message}`);
            }
          })

这里需要注意的是:单独使用scheme是无法拉起的,会抛出异常,所以要使用下面的格式。

uri: 'link://www.example.com'

要对应被拉起方

 "scheme": "link",
 "host": "www.example.com"

2、使用startAbility实现
startAbility接口是将应用链接放入Want中,通过调用隐式Want匹配的方法触发应用跳转。

Button('DeepLink')
          .onClick(() =>{
            let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
            let want: Want = {
              uri: 'link://www.example.com', // 此处为实际应用链接
            };
            try {
              context.startAbility(want).then(() =>{
                hilog.info(DOMAIN_NUMBER, TAG, 'openLink success.');
              }).catch((err: BusinessError )=>{
                hilog.error(DOMAIN_NUMBER, TAG, `openLink failed. Code is ${err.code}, message is ${err.message}`);
              })
            }catch (e) {
              hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. Code is ${e.code}, message is ${e.message}`);
            }
          })

这里需要注意的是:
1、配置方式:

uri: 'link://www.example.com'

要对应被拉起方

 "scheme": "link",
 "host": "www.example.com"

如果写成下面这种方式是不对的:

uri: 'link://',
bundleName: 'www.example.com'

2、配置方式

"scheme": "link"

那么,拉起方只需要这样写就可以:

let want: Want = {
    uri: 'link://', // 此处为实际应用链接
    // bundleName: 'www.example.com' 如果使用bundleName字段,那么包名错误会导致无法正常拉起,这个地方需要特别注意
};

3、Web组件实现应用跳转(目前开发中没有遇到这里引用官方文档内容)
Web组件可以在onLoadIntercept的回调函数中实现应用跳转。

// DeepWebIndex.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const DOMAIN_NUMBER = 0xF811;
const TAG = '[Sample_PullLinking]';



struct DeepWebIndex {
  controller: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('index.html'), controller: this.controller })
        .onLoadIntercept((event) => {
          const url: string = event.data.getRequestUrl();
          if (url === 'link://www.example.com') {
            (this.getUIContext().getHostContext() as common.UIAbilityContext).openLink(url)
              .then(() => {
                hilog.info(DOMAIN_NUMBER, TAG, 'openLink success.');
              }).catch((err: BusinessError) => {
              hilog.error(DOMAIN_NUMBER, TAG, `openLink failed, err: ${JSON.stringify(err)}.`);
            });
            return true;
          }
          // 返回true表示阻止此次加载,否则允许此次加载
          return false;
        })
    }
  }
}

前端代码

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<h1>Hello World</h1>
<!--方式一、通过绑定事件window.open方法实现跳转-->
<button class="doOpenLink" onclick="doOpenLink()">跳转其他应用一</button>
<!--方式二、通过超链接实现跳转-->
<a href="link://www.example.com">跳转其他应用二</a>
</body>
</html>
<script>
    function doOpenLink() {
        window.open("link://www.example.com")
    }
</script>
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐