# 通过延迟链接跳转至应用详情页

#### 场景介绍

从5.0.3(15)版本开始，新增支持延迟链接能力。

当被分享用户未安装应用时，通过延迟链接能力，应用首次打开时，调用延迟链接接口，系统仍能获取用户之前点击的应用相关链接。在获取链接后，应用可直接跳转至对应的详情页，无需先跳转至应用首页，从而提升用户体验和链接的转化率。

例如：华为阅读结合App Linking Kit延迟链接能力，实现了即使用户未安装应用，点击链接完成下载并首次打开时，仍能直接跳转至预设页面（如书籍详情页）。与传统方式（需先打开APP再手动定位内容）相比，操作步骤减少了43%。

#### 原理机制

#### 一次性机制

延迟链接只能获取一次，获取后，系统会从缓存中删除该链接；后续调用时，返回为空。

#### 缓存机制

*   缓存时效性：系统缓存链接的最大时长为10分钟，超过则自动删除该缓存链接。
    
*   缓存条数限制：系统最多缓存的链接条目数为50条，超过则自动删除最早的缓存链接。
    

#### 前提条件

1.  目标方应用已配置App Linking应用链接。
    
2.  该能力目前仅适用于5.0.3(15)及以上版本的HarmonyOS应用。
    

#### 约束与限制

*   支持Phone、Tablet设备。并且从6.1.0(23)版本开始，新增支持PC/2in1设备。
    
*   只能获取通过App Linking域名校验的应用链接，请参见在AGC为应用创建关联的网址域名。建议在首次启动签署隐私协议后再调用延迟链接接口，确保此时域名校验通过。
    

#### 开发步骤

1.  获取延迟链接。
    
    1.  在入口类文件页面Index.ets中添加如下代码。当应用首次启动时，调用deferredLink.popDeferredLink()接口，获取用户此前点击的该应用相关链接。
        
        ```
        import { deferredLink } from '@kit.AppLinkingKit';
        import { hilog } from '@kit.PerformanceAnalysisKit';
        
        @Entry
        @Component
        struct Index {
        pageStack: NavPathStack = new NavPathStack();
           build() {
              Column() {
                 Navigation(this.pageStack) {
                    Button("获取延迟链接").onClick(() => {
                       // 应用首次启动时，获取用户此前点击的该应用相关链接
                       deferredLink.popDeferredLink().then((link: string) => {
                          hilog.info(0x0000, 'testTag', `Succeeded in getting deferred link, result: ${link}`);
                       }).catch(() => {
                         // 发生未知错误
                          hilog.error(0x0000, 'testTag', `Failed to get deferred link.`);
                       })
                    })
                    // ...
                 }
                 // ...
              }
           }
        }
        ```
        
    2.  根据自身业务逻辑配置链接，实现跳转到对应的详情页面。
        
        ```
        import { deferredLink } from '@kit.AppLinkingKit';
        import { hilog } from '@kit.PerformanceAnalysisKit';
        import { url } from '@kit.ArkTS';
        
        @Entry
        @Component
        struct Index {
          pageStack: NavPathStack = new NavPathStack();
          build() {
            Column() {
              Navigation(this.pageStack) {
                Button("获取延迟链接").onClick(() => {
                  // 应用首次启动时，获取用户此前点击的该应用相关链接
                  deferredLink.popDeferredLink().then((link: string) => {
                    hilog.info(0x0000, 'testTag', `Succeeded in getting deferred link, result: ${link}`);
                    // 若延迟链接不为空，开发者可根据自身业务逻辑配置链接，跳转至详情页面
                    if (link) {
                      // 根据业务逻辑配置链接，自行跳转至详情页面
                      // 如传入的url为：<>
                      // 从链接中解析query参数，拿到参数后，开发者可根据自己的业务需求进行后续的处理，示例如下：
                      try {
                        let urlObject = url.URL.parseURL(link);
                        let pageName = urlObject.params.get('pageName');
                        this.pageStack.pushPath({ name: pageName });
                      } catch (error) {
                        hilog.error(0x0000, 'testTag', `Failed to parse url.`);
                      }
                    }
                  }).catch(() => {
                    // 发生未知错误
                    hilog.error(0x0000, 'testTag', `Failed to get deferred link.`);
                  })
                })
                // ...
              }
              // ...
            }
          }
        }
        ```
        
2.  验证应用被拉起效果。
    
    拉起方应用可调用UIAbilityContext.openLink()接口，传入目标应用的链接，从而拉起目标应用。
    
    openLink接口提供了两种拉起目标应用的方式，开发者可根据业务需求进行选择。
    
    *   方式一： 仅以App Linking的方式打开应用。
        
        将appLinkingOnly参数设为true，若有App Linking匹配的应用，则直接打开目标应用。若无App Linking匹配的应用，则抛异常给开发者进行处理。
        
        适用于无法打开目标应用时，开发者做了相应的异常处理。例如：拉起方应用集成了ArkWeb，当目标应用不存在时，可通过ArkWeb打开链接。
        
    *   方式二： 以App Linking优先的方式打开应用。
        
        将appLinkingOnly参数设为false或者不传，若有App Linking匹配的应用，则直接打开目标应用。若无App Linking匹配的应用，则尝试以浏览器打开链接的方式打开应用。
        
        适用于无法打开目标应用时，开发者未做任何处理。此时目标应用不存在时，会通过系统浏览器打开链接。
        
    
    本文为了方便验证App Linking的配置是否正确，选择方式一，示例如下。
    
    1.  在“entry/src/main/ets/common”目录下添加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;
          }
        }
        ```
        
    2.  在“entry/src/main/ets/entryability/EntryAbility.ets”文件中导入GlobalContext，在onCreate方法中使用GlobalContext.initContext(this.context)初始化全局应用上下文。
    3.  在“entry/src/main/ets/pages/Index.ets”文件中，使用UIAbilityContext.openLink()接口打开应用。
        
        ```
        import { hilog } from '@kit.PerformanceAnalysisKit';
        import { BusinessError } from '@kit.BasicServicesKit';
        import { GlobalContext } from '../common/GlobalContext';
        
        @Entry
        @Component
        struct Index {
          build() {
            Button('start link', { type: ButtonType.Capsule, stateEffect: true })
              .width('87%')
              .height('5%')
              .margin({ bottom: '12vp' })
              .onClick(() => {
                let context = GlobalContext.getContext();
                let link: string = "";
                // 仅以App Linking的方式打开应用
                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}`);
                  })
              })
          }
        }
        ```
        
3.  安装拉起方应用，点击拉起方应用中的跳转按钮。
    
    如果此时目标方应用未安装，会抛出系统异常。
    
4.  安装目标方应用后，会根据获取的延迟链接直接跳转到目标方应用的详情页面。