DEV Community

Cover image for HarmonyOS Deep Linking Development Guide: Enabling Flexible App Navigation
kouwei qing
kouwei qing

Posted on

HarmonyOS Deep Linking Development Guide: Enabling Flexible App Navigation

HarmonyOS Deep Linking Development Guide: Enabling Flexible App Navigation

I. Introduction to Deep Linking

Deep Linking is an app navigation technology provided by HarmonyOS, which locates and launches eligible installed apps using URI information. When multiple matching apps exist, the system automatically pops up a selection dialog for users to choose the target app.

Core Features:

  • Navigation based on installed local apps
  • Selection mechanism for multiple matching apps
  • Flexible URI matching rules
  • Suitable for various inter-app interaction scenarios

II. Implementation Principle

Deep Linking queries and launches target apps through URI matching in the implicit Want matching mechanism. The system parses incoming URI information and searches for apps capable of handling the URI locally according to predefined rules.

Key Points of URI Matching Rules:

  • Scheme: Custom identifier without special characters, not starting with "ohos"
  • Host: Specified domain name or identifier
  • Path: Optional, for precise path matching
  • Query Parameters: Optional, for passing parameters

III. Configuration Guide for Target Apps

1. Configure module.json5 File

To allow other apps to access your app via Deep Linking, you must correctly set the skills tag in the module.json5 configuration file.

Configuration Key Points:

  • The skills tag includes a default skill object identifying the app entry.
  • App navigation links should not be configured in the default skill object.
  • Create independent skill objects for each navigation scenario.
  • Configure multiple skill objects for multiple scenarios.

Configuration Example:

{
  "module": {
    // ...Other configurations
    "abilities": [
      {
        // ...Other capability configurations
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "ohos.want.action.home"
            ]
          },
          {
            "actions": [
              // Note: actions cannot be empty to avoid matching failure
              "ohos.want.action.viewData"
            ],
            "uris": [
              {
                // scheme is mandatory, customizable (not starting with http, https, file)
                "scheme": "link",
                // host is mandatory, configure the matching domain name
                "host": "www.example.com"
              }
            ]
          }
          // Add more skill objects for multiple navigation scenarios
        ]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Notes:

  • The scheme can be customized but should not use "https", "http", "file", etc., which are handled by system browsers.
  • Each navigation scenario requires an independent skill object configuration.
  • The actions field must not be empty to avoid matching failure on the target side.

IV. Acquire and Parse Incoming App Links

When other apps navigate to your app via Deep Linking, you need to acquire and parse the incoming URI information in the app's UIAbility.

Example Code:

// Take EntryAbility.ets as an example
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 {
    // Get the incoming link from want
    // Example: link://www.example.com/programs?action=showall
    let uri = want?.uri;
    if (uri) {
      // Parse parameters in the URI
      let urlObject = url.URL.parseURL(want?.uri);
      let action = urlObject.params.get('action');

      // Execute corresponding operations based on parameters
      if (action === "showall") {
         // Logic to display all programs
         // ...
      }
      // Handle more parameters and logic as needed
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

V. Implement Navigation for Launching Apps

Launching apps can implement Deep Linking navigation in multiple ways. Below are three common implementation methods.

1. Use openLink for App Navigation

The openLink interface provides a simple way to implement app navigation.

Example Code:

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

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 context = this.getUIContext().getHostContext() as common.UIAbilityContext;
        let link: string = "link://www.example.com";
        let openLinkOptions: OpenLinkOptions = {
          appLinkingOnly: false  // Key configuration: Use Deep Linking mode
        };

        try {
          context.openLink(link, openLinkOptions)
            .then(() => {
              hilog.info(DOMAIN_NUMBER, TAG, 'open link success.');
            }).catch((err: BusinessError) => {
              hilog.error(DOMAIN_NUMBER, TAG, `open link 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}`);
        }
      })
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Set appLinkingOnly to false to use Deep Linking.
  • Setting it to true will attempt App Linking, possibly causing navigation failure.

2. Use startAbility for App Navigation

The startAbility interface triggers app navigation via implicit Want matching, providing lower-level control.

Example Code:

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

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 = this.getUIContext().getHostContext() as common.UIAbilityContext;
        let want: Want = {
          uri: "link://www.example.com"  // Set the target URI
        };

        try {
          context.startAbility(want).then(() => {
            hilog.info(DOMAIN_NUMBER, TAG, 'start ability success.');
          }).catch((err: BusinessError) => {
            hilog.error(DOMAIN_NUMBER, TAG, `start ability failed. Code is ${err.code}, message is ${err.message}`);
          });
        } catch (paramError) {
          hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${paramError.code}, message is ${paramError.message}`);
        }
      })
  }
}
Enter fullscreen mode Exit fullscreen mode

Notes:

  • Ensure the URI in want matches the target app's configured URI rules.
  • The caller must pass correct action and entity for matching.

3. Use Web Components for App Navigation

Deep Linking can also be implemented in web pages by intercepting page loading events or binding click events.

Web Component Example Code:

// index.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } 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 === 'link://www.example.com') {
            // Intercept specific URL and use Deep Linking to navigate
            (this.getUIContext().getHostContext() as common.UIAbilityContext).openLink(url)
              .then(() => {
                console.log('openLink success');
              }).catch((err: BusinessError) => {
                console.error('openLink failed, err:' + JSON.stringify(err));
              });
            return true;  // Prevent further loading of this URL
          }
          // Return false to allow normal page loading
          return false;
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Front-end Page Code:

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<h1>Hello World</h1>
<!-- Method 1: Implement navigation via window.open event binding -->
<button class="doOpenLink" onclick="doOpenLink()">Jump to Another App 1</button>
<!-- Method 2: Implement navigation via hyperlink -->
<a href="link://www.example.com">Jump to Another App 2</a>
</body>
</html>
<script>
    function doOpenLink() {
        window.open("link://www.example.com")
    }
</script>
Enter fullscreen mode Exit fullscreen mode

Working Principle:

  • The Web component intercepts loading of specific URLs via onLoadIntercept.
  • When a Deep Linking URI is detected, it calls the openLink interface for app navigation.
  • Returning true prevents the Web component from loading the URL.
  • Returning false allows normal page loading.

VI. Summary and Best Practices

Comparison Between Deep Linking and App Linking

Feature Deep Linking App Linking
Target App Requirement Must be installed Works whether installed or not
Navigation Experience May show app selection dialog Smoother, automatically handles installation status
Security Relies on URI matching rules Adds domain verification for higher security
Configuration Complexity Relatively simple Relatively complex, requires additional domain configuration

Best Practice Recommendations

  1. URI Design Specifications

    • Use meaningful schemes, avoiding common protocols like http, https, file.
    • Design a clear host structure for easy management and identification.
    • Reasonably use path and query parameters to传递 information.
  2. Multi-scenario Handling

    • Create independent skill objects for different navigation scenarios.
    • Ensure actions are not empty for each scenario.
    • Consider the integrity and security of parameter passing.
  3. Error Handling

    • Add appropriate error handling logic when calling navigation interfaces.
    • Consider fallback solutions when the target app is not installed.
    • Log navigation failures for analysis and optimization.
  4. Testing and Verification

    • Test navigation in multiple scenarios, including:
      • Target app installed
      • Target app not installed
      • Multiple apps matching the same URI
    • Verify the correctness of parameter passing.

Through this guide, developers can master HarmonyOS Deep Linking implementation, adding flexible inter-app navigation to their apps and enhancing user experience and interoperability.

Top comments (0)