HarmonyOS Scan Kit 扫码直达服务详解:从配置到上线的全链路实战
HarmonyOS Scan Kit 扫码直达服务详解:从配置到上线的全链路实战
前言
在传统移动应用中,用户需要先打开应用,找到扫码入口,再对准二维码扫描,整个操作路径较长。而 HarmonyOS Scan Kit 创新性地推出了扫码直达服务——用户只需在控制中心下拉扫一扫,扫描二维码后即可直接跳转到应用的指定服务页面,实现一步直达的极致体验。
扫码直达是 Scan Kit 的王牌特性,也是华为官方强烈推荐优先接入的能力。本文将深度剖析扫码直达的技术原理、配置流程、代码实现以及验证方法,带你从零到一完成扫码直达的接入。
核心价值:扫码直达让用户无需打开应用即可通过系统级扫码入口直达服务页,大幅缩短用户操作路径,提升转化率。美团单车、丰巢、企业微信等头部应用已接入此能力。
一、扫码直达概念解析
1.1 什么是扫码直达
扫码直达是一种系统级扫码路由服务。开发者将域名注册到扫码直达服务后,用户可通过控制中心等系统级常驻入口扫描应用的二维码或条形码,系统会自动解析码值并直接跳转到应用对应服务页,无需用户手动打开应用。
扫码直达的核心工作流程:
- 开发者完成域名注册和 App Linking 配置
- 用户通过 HarmonyOS 系统扫码入口发起扫码请求
- 系统调用底层能力解析码值,查询码值对应的应用信息
- 系统自动拉起目标应用,跳转到指定服务页面

扫码直达从用户扫码到应用服务页的完整数据流转流程
1.2 扫码直达 vs 应用内扫码
| 对比维度 | 扫码直达 | 应用内扫码 |
|---|---|---|
| 扫码入口 | 控制中心下拉(系统级) | 应用内扫码按钮 |
| 操作步骤 | 下拉→扫码→直达 | 打开应用→找到扫码→扫码 |
| 用户路径 | 2步 | 3-4步 |
| 应用未安装 | 网页兜底(HTTPS) | 无法使用 |
| 接入成本 | 配置域名+处理Want | 集成扫码SDK |
| 适用场景 | 浅层入口、快速触达 | 应用内功能入口 |
1.3 扫码直达的优势
接入扫码直达服务能为应用带来以下核心价值:
- 更浅层的扫码入口:用户无需打开应用,从控制中心即可扫码
- 更便捷的服务体验:扫码后一步直达应用内指定页面
- HarmonyOS 强大的扫码能力:享受系统级 AI 算法加持的扫码体验
- 更容易触达用户的全新渠道:系统级入口带来额外的流量来源
- 应用未安装时的网页兜底:HTTPS 链接支持应用未安装时浏览器打开
二、扫码直达技术原理
2.1 底层技术架构
扫码直达基于 App Linking 能力实现,底层依赖以下技术组件:
- App Linking:HarmonyOS 提供的深度链接服务,支持 HTTPS 网址与应用内页面的映射
- Want(意图):HarmonyOS 中用于应用间跳转和组件启动的核心机制
- UIAbility 生命周期:通过
onCreate和onNewWant回调接收系统传入的链接信息
2.2 冷启动与热启动场景
扫码直达需要处理两种启动场景:
| 启动场景 | 触发条件 | 数据接收方式 | 处理回调 |
|---|---|---|---|
| 冷启动 | 应用未在后台运行 | 系统创建新的 UIAbility 实例 | onCreate(want: Want) |
| 热启动 | 应用已在后台运行 | 系统复用已有 UIAbility 实例 | onNewWant(want: Want) |
关键提示:冷启动和热启动场景都需要正确处理,否则可能导致用户在应用已打开时扫码无法跳转到正确页面。两种场景下的 Want 参数处理逻辑应该保持一致。
2.3 数据流转流程
扫码直达的数据流转流程如下:
- 用户扫描二维码 → 2. 系统解析码值(HTTPS URL) → 3. 系统匹配 App Linking 配置的域名 → 4. 系统构建 Want 对象,携带 URI 信息 → 5. 拉起目标 UIAbility → 6. 应用解析 Want 中的 URI → 7. 应用路由到对应服务页面
三、使用限制与约束
3.1 使用限制
接入扫码直达服务前,请确认以下限制条件:
| 限制项 | 说明 |
|---|---|
| 协议要求 | 仅支持 HTTPS 架构的网页链接接入,HTTP 需要联系工单 |
| 地域限制 | 仅支持中国境内使用(香港、澳门、台湾除外) |
| 签名要求 | 不能使用 DevEco Studio 自动签名,必须使用手动签名 |
| 设备支持 | 仅支持 Phone 和 Tablet 设备 |
| 域名要求 | 需要拥有可验证的 HTTPS 域名 |
3.2 适用场景建议
扫码直达最适合以下业务场景:
- 共享单车开锁:用户扫码直接开锁,美团单车已实现
- 快递取件:用户扫码直接取件,丰巢已实现
- 企业办公:扫码登录、扫码签到,企业微信已实现
- 餐饮点餐:扫码直接进入点餐页面
- 活动签到:扫码直达活动签到页面
四、开发准备

扫码直达开发准备:在AGC控制台开通App Linking服务并完成域名注册与验证
4.1 AGC 控制台配置
在接入扫码直达之前,需要在 AppGallery Connect 控制台完成以下配置:
- 登录 AppGallery Connect 控制台
- 创建或选择已有项目和应用
- 在"构建"菜单中找到 App Linking 服务
- 开通 App Linking 服务
- 在 App Linking 中配置二维码/条形码关联的网址域名
4.2 域名验证
在 App Linking 中配置域名后,需要进行域名所有权验证:
// 需要在你的 HTTPS 域名服务器根目录下放置验证文件
// 文件路径示例: https://www.example.com/.well-known/assetlinks.json
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.yourapp",
"sha256_cert_fingerprints": [
"你的应用签名证书的SHA256指纹"
]
}
}
]
4.3 module.json5 配置
在应用的 module.json5 文件中关联已配置的域名:
{
"module": {
"name": "entry",
"type": "entry",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
},
{
"actions": [
"ohos.want.action.viewData"
],
"entities": [
"entity.system.default"
],
"uris": [
{
"scheme": "https",
"host": "www.example.com",
"path": "scan"
}
]
}
]
}
]
}
}
五、代码实现
5.1 核心代码:EntryAbility 中处理扫码直达
以下是扫码直达的完整核心代码实现,需要在 EntryAbility.ets 中编写:
import { UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { router, window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[ScanAccess]';
export default class EntryAbility extends UIAbility {
private page: string = 'pages/Index';
private uiContext?: UIContext;
/**
* 冷启动场景:通过 onCreate 回调获取码值信息
* 当应用未在后台运行时,系统创建新的 UIAbility 实例
*/
onCreate(want: Want): void {
hilog.info(0x0001, TAG, 'Succeeded in getting want in onCreate');
// 从 want 中获取传入的链接信息
// 示例:传入的 url 为 https://www.example.com/scan?productId=12345
this.getRouterUri(want);
}
/**
* 热启动场景:通过 onNewWant 回调获取码值信息
* 当应用已在后台运行时,系统复用已有 UIAbility 实例
*/
onNewWant(want: Want): void {
hilog.info(0x0001, TAG, 'Succeeded in getting want in onNewWant');
// 从 want 中获取传入的链接信息
this.getRouterUri(want);
}
/**
* 窗口阶段创建
*/
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(0x0001, TAG, 'Ability onWindowStageCreate');
try {
windowStage.getMainWindow().then((windowObj: window.Window) => {
try {
windowStage.loadContent(this.page).then(() => {
hilog.info(0x0001, TAG, 'Succeeded in loading the content.');
try {
this.uiContext = windowObj.getUIContext();
hilog.info(0x0001, TAG, 'Succeeded in getting UIContext.');
} catch (err) {
const error = err as BusinessError;
hilog.error(0x0001, TAG,
`Failed to get UIContext by windowObj. Code: ${error.code}.`);
}
}).catch((err: BusinessError) => {
hilog.error(0x0001, TAG,
`Failed to load the content. Code: ${err.code}.`);
});
} catch (err) {
const error = err as BusinessError;
hilog.error(0x0001, TAG,
`Failed to load the content. Code: ${error.code}.`);
}
}).catch((err: BusinessError) => {
hilog.error(0x0001, TAG,
`Failed to get MainWindow. Code: ${err.code}.`);
});
} catch (err) {
const error = err as BusinessError;
hilog.error(0x0001, TAG,
`Failed to get MainWindow. Code: ${error.code}.`);
}
}
/**
* 解析扫码结果,跳转相应页面
* @param want 系统传入的 Want 对象,包含 URI 信息
*/
private getRouterUri(want: Want): void {
const uri: string | undefined = want?.uri;
if (!uri) {
hilog.warn(0x0001, TAG, 'No URI found in want');
return;
}
hilog.info(0x0001, TAG, `Received URI: ${uri}`);
// 解析 URI 中的路径和参数
// 示例: https://www.example.com/scan?productId=12345
this.page = 'pages/Access';
if (this.uiContext) {
const status: router.RouterState =
this.uiContext.getRouter().getState();
if (status && status.name !== 'Access') {
try {
// 根据 URI 参数做业务处理
this.uiContext.getRouter().pushUrl({
url: 'pages/Access',
params: {
uri: uri
}
}).catch((err: BusinessError) => {
hilog.error(0x0001, TAG,
`Failed to pushUrl by getRouter. Code: ${err.code}.`);
});
} catch (err) {
const error = err as BusinessError;
hilog.error(0x0001, TAG,
`Failed to pushUrl by getRouter. Code: ${error.code}.`);
}
}
}
}
}
5.2 高级路由处理:解析 URI 参数
在实际项目中,你需要从 URI 中提取具体的业务参数,实现精准路由:
import { router } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[ScanRouter]';
/**
* 扫码直达路由管理器
* 负责解析 URI 并路由到对应的业务页面
*/
export class ScanRouter {
/**
* 解析 URI 并进行页面路由
* @param uri 扫码直达传入的 URI
* @param uiContext UIContext 实例
*/
static navigate(uri: string, uiContext: UIContext): void {
try {
// 解析 URI 示例: https://www.example.com/scan/product?id=12345&type=detail
const urlObj = new URL(uri);
const path = urlObj.pathname; // /scan/product
const params = new URLSearchParams(urlObj.search);
hilog.info(0x0001, TAG,
`Path: ${path}, Params: ${params.toString()}`);
// 根据路径路由到不同页面
switch (path) {
case '/scan/product':
this.navigateToProduct(uiContext, params);
break;
case '/scan/order':
this.navigateToOrder(uiContext, params);
break;
case '/scan/payment':
this.navigateToPayment(uiContext, params);
break;
case '/scan/profile':
this.navigateToProfile(uiContext, params);
break;
default:
this.navigateToDefault(uiContext, uri);
break;
}
} catch (err) {
hilog.error(0x0001, TAG,
`Failed to parse URI: ${uri}`);
this.navigateToDefault(uiContext, uri);
}
}
/**
* 路由到商品详情页
*/
private static navigateToProduct(
uiContext: UIContext,
params: URLSearchParams
): void {
const productId = params.get('id') || '';
const type = params.get('type') || 'detail';
uiContext.getRouter().pushUrl({
url: 'pages/ProductDetail',
params: {
productId: productId,
source: 'scan_direct',
type: type
}
}).catch((err: Error) => {
hilog.error(0x0001, TAG,
`Failed to navigate to ProductDetail: ${err.message}`);
});
}
/**
* 路由到订单页面
*/
private static navigateToOrder(
uiContext: UIContext,
params: URLSearchParams
): void {
const orderId = params.get('id') || '';
uiContext.getRouter().pushUrl({
url: 'pages/OrderDetail',
params: {
orderId: orderId,
source: 'scan_direct'
}
}).catch((err: Error) => {
hilog.error(0x0001, TAG,
`Failed to navigate to OrderDetail: ${err.message}`);
});
}
/**
* 路由到支付页面
*/
private static navigateToPayment(
uiContext: UIContext,
params: URLSearchParams
): void {
const amount = params.get('amount') || '0';
const merchantId = params.get('merchantId') || '';
uiContext.getRouter().pushUrl({
url: 'pages/Payment',
params: {
amount: amount,
merchantId: merchantId,
source: 'scan_direct'
}
}).catch((err: Error) => {
hilog.error(0x0001, TAG,
`Failed to navigate to Payment: ${err.message}`);
});
}
/**
* 路由到个人资料页面
*/
private static navigateToProfile(
uiContext: UIContext,
params: URLSearchParams
): void {
const userId = params.get('userId') || '';
uiContext.getRouter().pushUrl({
url: 'pages/Profile',
params: {
userId: userId,
source: 'scan_direct'
}
}).catch((err: Error) => {
hilog.error(0x0001, TAG,
`Failed to navigate to Profile: ${err.message}`);
});
}
/**
* 默认路由(无法识别路径时)
*/
private static navigateToDefault(
uiContext: UIContext,
uri: string
): void {
uiContext.getRouter().pushUrl({
url: 'pages/ScanResult',
params: {
uri: uri,
source: 'scan_direct'
}
}).catch((err: Error) => {
hilog.error(0x0001, TAG,
`Failed to navigate to ScanResult: ${err.message}`);
});
}
}
5.3 在 EntryAbility 中使用 ScanRouter
import { UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { ScanRouter } from '../utils/ScanRouter';
const TAG: string = '[EntryAbility]';
export default class EntryAbility extends UIAbility {
private uiContext?: UIContext;
/**
* 第一个启动时调用(冷启动 + 扫码直达)
*/
onCreate(want: Want): void {
hilog.info(0x0001, TAG, 'onCreate called');
this.handleScanUri(want, 'onCreate');
}
/**
* 应用已启动后再次调用(热启动 + 扫码直达)
*/
onNewWant(want: Want): void {
hilog.info(0x0001, TAG, 'onNewWant called');
this.handleScanUri(want, 'onNewWant');
}
/**
* 统一处理扫码直达 URI
*/
private handleScanUri(want: Want, source: string): void {
const uri: string | undefined = want?.uri;
if (!uri) {
hilog.info(0x0001, TAG,
`No URI in ${source}, normal launch`);
return;
}
hilog.info(0x0001, TAG,
`Received URI from ${source}: ${uri}`);
if (this.uiContext) {
// UI 已加载,直接路由
ScanRouter.navigate(uri, this.uiContext);
} else {
// UI 尚未加载,保存 URI 等加载完成后处理
this.pendingUri = uri;
}
}
private pendingUri?: string;
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index').then(() => {
windowStage.getMainWindow().then((windowObj: window.Window) => {
this.uiContext = windowObj.getUIContext();
// 处理待处理的 URI
if (this.pendingUri && this.uiContext) {
ScanRouter.navigate(this.pendingUri, this.uiContext);
this.pendingUri = undefined;
}
});
});
}
}
六、目标页面实现
6.1 接收扫码直达参数
在目标页面中接收从 EntryAbility 传递过来的参数:
import { router } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[AccessPage]';
@Entry
@Component
struct AccessPage {
@State pageTitle: string = '扫码直达';
@State uri: string = '';
@State source: string = '';
aboutToAppear(): void {
// 获取路由传递的参数
const params = router.getParams() as Record<string, Object>;
if (params) {
this.uri = (params['uri'] as string) || '';
this.source = (params['source'] as string) || 'unknown';
hilog.info(0x0001, TAG,
`AccessPage params - uri: ${this.uri}, source: ${this.source}`);
}
}
build() {
Column() {
// 标题栏
Row() {
Text(this.pageTitle)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Button('返回')
.onClick(() => {
router.back();
})
}
.width('100%')
.padding(16)
.justifyContent(FlexAlign.SpaceBetween)
// 内容区
Column() {
Text('扫码直达成功!')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
Text(`来源: ${this.source}`)
.fontSize(16)
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.margin({ bottom: 10 })
Text(`URI: ${this.uri}`)
.fontSize(14)
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor($r('sys.color.ohos_id_color_sub_background'))
}
}
七、生成扫码直达二维码
7.1 使用 Scan Kit 生成二维码
接入扫码直达后,你需要生成对应的二维码供用户扫描。以下是使用 Scan Kit 生成二维码的代码:
import { scanCore, generateBarcode } from '@kit.ScanKit';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[QRGenerator]';
@Entry
@Component
struct QRCodePage {
@State pixelMap: image.PixelMap | undefined = undefined;
build() {
Column() {
// 显示生成的二维码
if (this.pixelMap) {
Column() {
Image(this.pixelMap)
.width(300)
.height(300)
.objectFit(ImageFit.Contain)
Text('扫码即可直达应用服务页')
.fontSize(14)
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.margin({ top: 12 })
}
.alignItems(HorizontalAlign.Center)
}
Button('生成扫码直达二维码')
.margin({ top: 20 })
.onClick(() => {
this.generateQRCode();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
private generateQRCode(): void {
// 扫码直达的 URL(需要与 App Linking 配置的域名一致)
const content: string =
'https://www.example.com/scan/product?id=12345&type=detail';
const options: generateBarcode.CreateOptions = {
scanType: scanCore.ScanType.QR_CODE,
width: 400,
height: 400,
margin: 2,
level: generateBarcode.ErrorCorrectionLevel.LEVEL_H,
backgroundColor: 0xFFFFFF,
pixelMapColor: 0x000000
};
try {
generateBarcode.createBarcode(content, options)
.then((pixelMap: image.PixelMap) => {
this.pixelMap = pixelMap;
hilog.info(0x0001, TAG, 'QR code generated successfully');
})
.catch((err: BusinessError) => {
hilog.error(0x0001, TAG,
`Failed to generate QR code. Code: ${err.code}, message: ${err.message}`);
});
} catch (err) {
const error = err as BusinessError;
hilog.error(0x0001, TAG,
`Failed to createBarcode. Code: ${error.code}, message: ${error.message}`);
}
}
}
八、开发后验证
8.1 验证步骤
完成开发和配置后,按照以下步骤验证扫码直达功能:
- 将配置好域名映射关系的测试应用安装到本地设备
- 生成一个指向你配置的 URL 的二维码(如
https://www.example.com/scan/product?id=12345) - 在 HarmonyOS 设备上下拉控制中心,点击扫一扫图标
- 扫描生成的二维码
- 验证系统是否正确拉起你的应用并跳转到指定页面
8.2 验证清单
| 验证项 | 验证内容 | 预期结果 |
|---|---|---|
| 冷启动验证 | 应用未运行时扫码 | 应用启动并跳转到指定页面 |
| 热启动验证 | 应用在后台时扫码 | 应用切换到前台并跳转到指定页面 |
| 参数传递验证 | 检查 URI 中的参数是否正确 | 参数正确传递到目标页面 |
| 页面路由验证 | 检查是否正确跳转到目标页面 | 跳转到预期页面 |
| 错误处理验证 | 扫码不支持的 URL 格式 | 应用能正常处理异常 |
8.3 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 扫码后不拉起应用 | 域名未正确配置 | 检查 App Linking 中的域名配置 |
| 拉起应用但参数为空 | Want 参数未正确传递 | 检查 onCreate/onNewWant 中的参数处理 |
| 热启动不跳转 | 未处理 onNewWant |
确保同时处理冷启动和热启动 |
| 签名验证失败 | 使用了自动签名 | 切换为手动签名 |
| URL 格式不匹配 | skills 中 URI 配置错误 | 检查 module.json5 中的 URI 配置 |
九、扫码直达与其他能力的联动
9.1 与默认界面扫码联动
推荐同时接入扫码直达和默认界面扫码,让应用同时支持两种扫码方式:
import { scanBarcode, scanCore } from '@kit.ScanKit';
import { common } from '@kit.AbilityKit';
export class ScanService {
/**
* 系统扫码入口(扫码直达):用户通过控制中心扫码
* 已在 EntryAbility 中处理,无需额外代码
*/
/**
* 应用内扫码入口:用户通过应用内按钮扫码
*/
static async inAppScan(context: common.Context): Promise<string> {
const options: scanBarcode.ScanOptions = {
scanTypes: [scanCore.ScanType.QR_CODE],
enableMultiMode: false,
enableAlbum: true
};
const result = await scanBarcode.startScanForResult(context, options);
return result.originalValue || '';
}
}
9.2 与码图生成联动
使用码图生成能力生成带参数的扫码直达二维码:
import { scanCore, generateBarcode } from '@kit.ScanKit';
import { image } from '@kit.ImageKit';
export class QRCodeGenerator {
/**
* 生成扫码直达二维码
* @param path 目标页面路径
* @param params 页面参数
*/
static async generateDirectQRCode(
path: string,
params: Record<string, string>
): Promise<image.PixelMap> {
// 构建扫码直达 URL
const baseUrl = 'https://www.example.com';
const queryString = Object.entries(params)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
const content = `${baseUrl}${path}?${queryString}`;
const options: generateBarcode.CreateOptions = {
scanType: scanCore.ScanType.QR_CODE,
width: 400,
height: 400,
margin: 2,
level: generateBarcode.ErrorCorrectionLevel.LEVEL_H
};
return generateBarcode.createBarcode(content, options);
}
}
十、最佳实践总结
10.1 架构建议
在接入扫码直达时,建议遵循以下架构原则:
- 统一路由管理:创建专门的
ScanRouter类统一管理所有扫码直达的路由分发 - 冷热启动兼顾:在
onCreate和onNewWant中都处理 Want 参数 - 延迟路由处理:当 UI 未加载完成时,先保存 URI 等加载完成后再处理
- 参数校验:对 URI 中的参数进行有效性校验,防止异常输入
- 日志记录:记录扫码直达的完整链路日志,便于问题排查
10.2 性能优化
- 避免重复路由:检查当前页面是否已经是目标页面,避免重复跳转
- 异步处理:URI 解析和路由跳转使用异步方式,避免阻塞主线程
- 缓存 UIContext:在
onWindowStageCreate中缓存 UIContext,避免重复获取
10.3 安全性建议
- HTTPS 强制:确保所有扫码直达链接使用 HTTPS 协议
- 参数验证:对传入的 URI 参数进行白名单验证
- 签名验证:使用手动签名,确保应用来源可信
总结
本文深入讲解了 HarmonyOS Scan Kit 扫码直达服务的完整接入流程,从概念原理、配置准备、代码实现到验证测试,覆盖了扫码直达开发的全链路。
扫码直达是 Scan Kit 最具创新性的能力之一,它通过系统级扫码入口实现了一步直达的极致用户体验。相比传统应用内扫码,扫码直达大幅缩短了用户操作路径,为应用带来了全新的流量入口。
在下一篇文章中,我们将深入讲解默认界面扫码的开发实战,敬请期待!
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- 接入"扫码直达"服务:扫码直达
- App Linking 开发指南:App Linking
- Scan Kit 开发指南:开发指南
- 开发准备:开发准备
- 码图生成:码图生成
- 默认界面扫码:默认界面扫码
- 官方示例工程:Sample Code
- 开源鸿蒙跨平台社区:社区
更多推荐



所有评论(0)