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
]
}
]
}
}
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
}
}
}
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}`);
}
})
}
}
Key Points:
- Set
appLinkingOnly
tofalse
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}`);
}
})
}
}
Notes:
- Ensure the URI in
want
matches the target app's configured URI rules. - The caller must pass correct
action
andentity
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;
})
}
}
}
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>
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
-
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.
-
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.
-
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.
-
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.
- Test navigation in multiple scenarios, including:
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)