- path、pathStartWith、pathRegex的取值前后均不需要加斜杠/。
- 建议scheme和host中不要包含大写字母。
设备A如何使用隔空传送的传递App Linking链接直达设备B打开?
App Linking Kit(应用链接服务):通过App Linking应用链接拉起指定应用,实现应用间跳转。当应用已安装时,优先通过应用展示内容;若应用未安装,则通过系统浏览器展示网页版内容。
隔空传送:用户通过“一抓一放”手势实现跨设备文件分享(图片、视频、文档等)以及跨设备链接分享。

实现跨设备链接隔空传送分享流程如上,其中A设备应用为宿主应用,B设备应用为目标应用。需要分别实现目标方和宿主方应用配置。
目标应用配置:
{
"entities": [
// entities必须包含"entity.system.browsable"
"entity.system.browsable"
],
"actions": [
// actions必须包含"ohos.want.action.viewData"
"ohos.want.action.viewData"
],
"uris": [
{
// scheme须配置为https
"scheme": "https",
// host须配置为关联的网址域名,实际运行时替换为真实的App Linking链接域名
"host": "www.example.com",
// path可选,表示域名服务器上的目录或文件路径,例如www.example.com/path1中的path1
// 如果应用只能处理部分特定的path,则此处应该配置应用所支持的path,避免出现应用不能处理的path链接也被引流到应用中的问题
"path": "path1"
}
],
// domainVerify须设置为true
"domainVerify": true
} onCreate(want: Want): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
let uri = want?.uri;
if (uri) {
let urlObject = url.URL.parseURL(uri);
let index = urlObject.params.get('index') as string;
AppStorage.setOrCreate('GesturesShare_shareIndex', 'Result:' + index);
AppStorage.setOrCreate('GesturesShare_isShareLink', true);
hilog.info(DOMAIN, 'testTag', 'EntryAbility onCreate invoked. uri: %{public}s', uri);
}
}
onNewWant(want: Want): void {
let uri = want?.uri;
if (uri) {
let urlObject = url.URL.parseURL(uri);
let index = urlObject.params.get('index') as string;
AppStorage.setOrCreate('GesturesShare_shareIndex', 'Result:' + index);
AppStorage.setOrCreate('GesturesShare_isShareLink', true);
hilog.info(DOMAIN, 'testTag', 'EntryAbility onCreate invoked. uri: %{public}s', uri);
}
}
在Page页面显示接收的分享内容:
@StorageLink('GesturesShare_isShareLink') isShareLink: boolean = false;
@StorageLink('GesturesShare_shareIndex') shareResult: string = '隔空传送分享AppLinking';
build() {
RelativeContainer() {
Text(this.shareResult)
.fontSize('35fp')
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
} 不能使用DevEco Studio的自动签名功能,必须使用手动签名,否则无法拉起应用。
宿主应用配置:
private immersiveCallback = (sharableTarget: harmonyShare.SharableTarget) => {
let filePath = this.context.filesDir + '/gestures_immersive.png'; // 仅为示例 请替换正确的文件路径
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: utd.UniformDataType.HYPERLINK,
content: `App Linking链接?index=${this.shareIndex}`, // 须替换为真实的App Linking链接,拼接自定义参数。
thumbnailUri: fileUri.getUriFromPath(filePath),
title: '隔空传送分享卡片标题',
description: '隔空传送分享卡片描述'
});
sharableTarget.share(shareData);
this.shareIndex++;
}; onPageShow(): void {
this.immersiveListening();
}
onPageHide(): void {
this.immersiveDisablingListening();
}
private immersiveListening() {
harmonyShare.on('gesturesShare', this.immersiveCallback);
}
private immersiveDisablingListening() {
harmonyShare.off('gesturesShare', this.immersiveCallback);
} 完整代码:
EntryAbility:
import { ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { url } from '@kit.ArkTS';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
onCreate(want: Want): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
let uri = want?.uri;
if (uri) {
let urlObject = url.URL.parseURL(uri);
let index = urlObject.params.get('index') as string;
AppStorage.setOrCreate('GesturesShare_shareIndex', 'Result:' + index);
AppStorage.setOrCreate('GesturesShare_isShareLink', true);
hilog.info(DOMAIN, 'testTag', 'EntryAbility onCreate invoked. uri: %{public}s', uri);
}
}
onNewWant(want: Want): void {
let uri = want?.uri;
if (uri) {
let urlObject = url.URL.parseURL(uri);
let index = urlObject.params.get('index') as string;
AppStorage.setOrCreate('GesturesShare_shareIndex', 'Result:' + index);
AppStorage.setOrCreate('GesturesShare_isShareLink', true);
hilog.info(DOMAIN, 'testTag', 'EntryAbility onCreate invoked. uri: %{public}s', uri);
}
}
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
} Index.ets:
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri, fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
private shareIndex: number = 0;
aboutToAppear(): void {
try {
let filePath = this.context.filesDir + '/gestures_immersive.png'; // 仅为示例 请替换正确的文件路径
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let writeLen = fs.writeSync(file.fd,
(this.context.resourceManager.getMediaContentSync($r('app.media.gestures_immersive').id) as Uint8Array).buffer);
console.info('write data to file succeed and size is:' + writeLen);
fs.closeSync(file);
} catch (error) {
console.error(`getMediaContentSync error. Code: ${error?.code}, message: ${error?.message}`);
}
}
private immersiveCallback = (sharableTarget: harmonyShare.SharableTarget) => {
let filePath = this.context.filesDir + '/gestures_immersive.png'; // 仅为示例 请替换正确的文件路径
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: utd.UniformDataType.HYPERLINK,
content: `App Linking链接?index=${this.shareIndex}`, // 须替换为真实的App Linking链接,拼接自定义参数。
thumbnailUri: fileUri.getUriFromPath(filePath),
title: '隔空传送分享卡片标题',
description: '隔空传送分享卡片描述'
});
sharableTarget.share(shareData);
this.shareIndex++;
};
onPageShow(): void {
this.immersiveListening();
}
onPageHide(): void {
this.immersiveDisablingListening();
}
private immersiveListening() {
harmonyShare.on('gesturesShare', this.immersiveCallback);
}
private immersiveDisablingListening() {
harmonyShare.off('gesturesShare', this.immersiveCallback);
}
@StorageLink('GesturesShare_isShareLink') isShareLink: boolean = false;
@StorageLink('GesturesShare_shareIndex') shareResult: string = '隔空传送分享AppLinking';
build() {
RelativeContainer() {
Text(this.shareResult)
.fontSize('35fp')
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
}