Harmony OS 开发skill的方法及路径
利用 HarmonyOS 的 skills(也就是 Ability 能力声明,跟 Android 里的意图过滤器是一个东西)在一个 UIAbility 上同时声明四种入口能力——桌面图标启动、自定义深链、HTTPS 应用链接(App Linking)、系统分享接收,做成一套完整的、能自己测试的工程方案。
在应用里做好“链接地址到具体页面"的路由映射,保证冷启动和热启动都能正确跳转,再配上链接可达性检查和 H5 降级方案,这样从外部点链接到应用内页面展示就整个跑通,这样每加一个新入口,改代码、调参数、测时序通过修改两份配置文件就可以实现。
具体完成的功能安排如下表所示,
|
编号 |
功能 |
触发方式 |
实现要点 |
|
F1 |
应用入口能力声明 |
点击桌面图标 |
entity.system.home + ohos.want.action.home,入口这个 skill 里不放业务 uris |
|
F2 |
自定义深链带参直达 |
skilldemo://goods/detail?id=1001 |
viewData + browsable + scheme/host/pathStartWith;解析 query 后直达商品详情页并携带业务参数 |
|
F3 |
多业务路由分发 |
skilldemo://order/list |
同一 Ability 通过路由映射表分流到不同页面;path 精确匹配示例 |
|
F4 |
HTTPS 应用链接直达 |
https://open.example.com/goods/1001 |
domainVerify: true,域名归属校验,防仿冒;未安装可由云端策略落到应用市场/网页 |
|
F5 |
接收系统分享 |
图库/浏览器分享面板选择本应用 |
sendData + 穷举 utd(纯文本、超链接、图片)+ maxFileSupported;用 ShareKit 解包 SharedRecord |
|
F6 |
冷/热启动一致投递 |
进程已存活时再次点击链接 |
launchType 配成 singleton,热启动才会回调 onNewWant;两个回调最后都走同一个分发函数 |
|
F7 |
链接协议 → 页面路由映射 |
新增入口场景时 |
一张 RULES 表把对外协议和对内页面的对应关系全写在一起;没匹配上的一律回首页兜底 |
|
F8 |
目标可达性探测与降级 |
应用内主动跳转 |
跳转前先用 bundleManager.canOpenLink() 探一下,openLink 分严格/降级两种模式;探测打不开就走 H5 |
|
F9 |
一键自测控制台 |
首页三个按钮 |
不用别的应用配合,自己就能把隐式拉起、探测、降级三条链路测一遍 |
|
F10 |
全链路可观测 |
拉起任意入口 |
统一 TAG 的 hilog 埋点,记录 action / uri / 路由结论 / 分享记录数 |
|
F11 |
参数白名单与重复消费防护 |
外部任意链接进来 |
仅解析白名单 query 键;同一链接键值去重,避免重复压栈 |
module.json5 里面 SkillsObj 官方只认 actions / entities / uris / permissions / domainVerify 这五个字段,所以我把四种入口分别写成独立的 skill 对象:
代码实现
这部分新加了两个文件:一个是生成和解析 App Link 的工具类,一个是封装碰一碰分享逻辑的管理器。
common/AppLinkUtil.ets
import { appLinking } from '@kit.AppLinkingKit';
// App Link 生成器
// 把内部的业务路由转成带域名校验的 HTTPS 链接
export class AppLinkUtil {
private static readonly DOMAIN = 'open.example.com';
private static readonly SCHEME = 'https';
// 根据路由路径生成 App Link
static async createAppLink(path: string, params?: Record<string, string>): Promise<string> {
let url = `${this.SCHEME}://${this.DOMAIN}/${path}`;
if (params) {
const query = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
query.append(key, value);
}
const queryString = query.toString();
if (queryString) {
url += `?${queryString}`;
}
}
// 注册到系统 App Linking 服务
try {
await appLinking.registerAppLink({
uri: url,
domainVerify: true,
expireTime: Date.now() + 7 * 24 * 60 * 60 * 1000 // 7天有效期
});
} catch (err) {
console.error(`[AppLinkUtil] registerAppLink failed: ${JSON.stringify(err)}`);
// 注册失败不影响使用,直接返回纯链接
}
return url;
}
// 解析收到的 App Link,提取路径和参数
static parseAppLink(uri: string): { path: string; params: Record<string, string> } {
try {
const url = new URL(uri);
const path = url.pathname.replace(/^\//, '');
const params: Record<string, string> = {};
url.searchParams.forEach((value, key) => {
params[key] = value;
});
return { path, params };
} catch (err) {
console.error(`[AppLinkUtil] parseAppLink failed: ${JSON.stringify(err)}`);
return { path: uri, params: {} };
}
}
}
|
skill |
actions |
entities |
uris 特征 |
附加 |
|
桌面入口 |
ohos.want.action.home |
entity.system.home |
不配置 |
— |
|
自定义深链 |
ohos.want.action.viewData |
entity.system.browsable |
scheme: skilldemo + host + pathStartWith/path |
— |
|
应用链接 |
ohos.want.action.viewData |
entity.system.browsable |
scheme: https + host: 关联域名 |
domainVerify: true |
|
分享接收 |
ohos.want.action.sendData |
可省 |
scheme: file + utd + maxFileSupported |
需穷举支持类型 |
更多推荐

所有评论(0)