【HarmonyOS】【进阶】鸿蒙原生实现应用间跳转之Deep Linking 原创

走向菜鸟的菜鸟
发布于 2025-3-13 10:21
浏览
1收藏

开发语言:ArkTs
开发工具:DevEco Studio 5.0.0 Release
API版本:API 12

使用Deep Linking实现应用间跳转,系统会根据接口中传入的uri信息,在本地已安装的应用中寻找到符合条件的应用并进行拉起(当匹配到多个应用时,会拉起应用选择框)。此种方式与iOS、Android中的配置scheme方式相同,都是通过特定scheme的方式拉起指定APP。

本文演示A应用(拉起方)拉起B应用(被拉起方)。

一、B应用(被拉起方)的代码及配置

1、配置B应用(被拉起方)的module.json5文件

为了能够支持被A应用(拉起方)访问,B应用(被拉起方)需要在module.json5配置文件中配置skills标签。

说明:skills标签下默认包含一个skill对象,用于标识应用入口。应用跳转链接不能在该skill对象中配置,需要创建独立的skill对象。如果存在多个跳转场景,需要在skills标签下创建不同的skill对象,否则会导致配置无法生效。
Deep Linking中的scheme取值支持自定义,可以为任意不包含特殊字符、非ohos开头的字符串。通常不为https、http、file,否则会拉起默认的系统浏览器。

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

2、在B应用(被拉起方)中获取并解析A应用(拉起方)传入的应用链接

在B应用(被拉起方)的UIAbilityonCreate()或者onNewWant()生命周期回调中,获取、解析A应用(拉起方)传入的应用链接。

// 以EntryAbility.ets为例
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { url } from '@kit.ArkTS';

export default class EntryAbility extends UIAbility {
  // 冷启动
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 从want中获取传入的链接信息。
    // 如传入的url为:blink://www.blink.com/open?action=scan
    let uri = want?.uri;
    if (uri) {
      // 从链接中解析query参数,拿到参数后,开发者可根据自己的业务需求进行后续的处理。
      let urlObject = url.URL.parseURL(want?.uri);
      let action = urlObject.params.get('action');
      // 例如,当action为showall时,展示所有的节目。
      if (action === "scan") {
         // 跳转扫一扫
         router.pushUrl({url: "pages/HMQRCodeScanPage"});
      }
    }
  }
	
  // 热启动
  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 从want中获取传入的链接信息。
	// 如传入的url为:blink://www.blink.com/open?action=scan
    let uri = want?.uri;
    if (uri) {
      // 从链接中解析query参数,拿到参数后,开发者可根据自己的业务需求进行后续的处理。
      let urlObject = url.URL.parseURL(want?.uri);
      let action = urlObject.params.get('action');
      // 例如,当action为showall时,展示所有的节目。
      if (action === "scan") {
         // 跳转扫一扫
         router.pushUrl({url: "pages/HMQRCodeScanPage"});
      }
    }
  }
}

二、A应用(拉起方)的代码配置

下面介绍如何使用openLink()startAbility()接口实现应用跳转,以及如何在Web组件中实现应用跳转。

1、判断B应用(被拉起方)是否安装

① 在entry模块的module.json5文件中配置querySchemes属性,声明想要查询的URL scheme

{
  "module": {
    //...
    "querySchemes": [
      "blink"
    ]
  }
}

② 调用bundleManager.canOpenLink()接口。

let canOpen = bundleManager.canOpenLink(link);

2、使用openLink()实现应用跳转

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

import { common, OpenLinkOptions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { bundleManager } from '@kit.AbilityKit';

const TAG: string = '[UIAbilityComponentsOpenLink]';
const DOMAIN_NUMBER: number = 0xFF00;

@Entry
@Component
struct Index {
  build() {
    Button('start link', { type: ButtonType.Capsule, stateEffect: true })
      .width('87%')
      .height('5%')
      .margin({ bottom: '12vp' })
      .onClick(() => {
        let link: string = "blink://www.blink.com/open?action=scan";
        let canOpen = bundleManager.canOpenLink(link);
		if (canOpen) {
		  try {
		    let context = getContext(this) as common.UIAbilityContext;
            context.openLink(link, {appLinkingOnly: false})
              .then(() => {
                hilog.info(DOMAIN_NUMBER, TAG, 'open link success.');
              }).catch((err: BusinessError) => {
                hilog.error(DOMAIN_NUMBER, TAG, `open link failed. `);
              });
          } catch (paramError) {
            hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. `);
          }
		} else {
		    hilog.error(DOMAIN_NUMBER, TAG, `Not installed to open link. `);
		}
      })
  }
}

3、使用startAbility()实现应用跳转

startAbility接口是将应用链接放入want中,通过调用隐式want匹配的方法触发应用跳转。通过startAbility接口启动时,还需要调用方传入待匹配的actionentity

import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { bundleManager } from '@kit.AbilityKit';

const TAG: string = '[UIAbilityComponentsOpenLink]';
const DOMAIN_NUMBER: number = 0xFF00;

@Entry
@Component
struct Index {
  build() {
    Button('start ability', { type: ButtonType.Capsule, stateEffect: true })
      .width('87%')
      .height('5%')
      .margin({ bottom: '12vp' })
      .onClick(() => {
        let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
        let link: string = "blink://www.blink.com/open?action=scan";
        let canOpen = bundleManager.canOpenLink(link);
		if (canOpen) {
		  let want: Want = {
            uri: link
	      };
	      try {
	        context.startAbility(want).then(() => {
	          hilog.info(DOMAIN_NUMBER, TAG, 'start ability success.');
	        }).catch((err: BusinessError) => {
	          hilog.error(DOMAIN_NUMBER, TAG, `start ability failed. `);
	        });
	      } catch (paramError) {
	        hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. `);
	      }
		} else {
		    hilog.error(DOMAIN_NUMBER, TAG, `Not installed to open link. `);
		}
      })
  }
}

4、使用Web组件实现应用跳转

Web组件需要跳转DeepLink链接应用时,可通过拦截回调onLoadIntercept中对定义的事件进行处理,实现应用跳转。

// index.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { common, bundleManager } from '@kit.AbilityKit';

@Entry
@Component
struct WebComponent {
  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.startWith('blink://')) {
            let canOpen = bundleManager.canOpenLink(link);
		    if (canOpen) {
 		      let context = getContext() as common.UIAbilityContext
		      context.openLink(url)
                .then(() => {
                  console.log('openLink success');
                }).catch((err: BusinessError) => {
                  console.error('openLink failed, err:' + JSON.stringify(err));
                });
			  return true;
		    } else {
		      hilog.error(DOMAIN_NUMBER, TAG, `Not installed to open link. `);
		    }
          }
          // 返回true表示阻止此次加载,否则允许此次加载
          return false;
        })
    }
  }
}

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2025-3-25 17:39:57修改
1
收藏 1
回复
举报
回复
    相关推荐