ITPub博客

首页 > 架构设计 > 设计模式 > 技术解读:HarmonyOS 扫码直达接入实战:系统扫、应用落,三步送用户进履约页

技术解读:HarmonyOS 扫码直达接入实战:系统扫、应用落,三步送用户进履约页

设计模式 作者:Flow_Official 时间:2026-09-16 12:51:30 0 删除 编辑

HarmonyOS 扫码直达接入实战:系统扫、应用落,三步送用户进履约页

本文基于 HarmonyOS 6.1 的「扫码直达」官方文档与 App Linking 接入指导整理。文中代码是为说明问题自写的完整示例,不是官方示例的搬运;API 名称、枚举取值与版本号等事实性信息均标注官方出处;涉及真机表现的部分已明确标注,未做任何实测数据编造。

本文基于 HarmonyOS 6.1 的「扫码直达」官方文档与 App Linking 接入指导整理。文中代码是为说明问题自写的完整示例,不是官方示例的搬运;API 名称、枚举取值与版本号等事实性信息均标注官方出处;涉及真机表现的部分已明确标注,未做任何实测数据编造。

HarmonyOS 扫码直达接入实战

引子:扫码之后,用户落在了首页

有个做本地生活的朋友跟V哥抱怨:他在应用里生成了一张"扫一扫点单"的码,发出去给用户。用户用系统的扫一扫一拍——应用是打开了,但停在了启动页。点单页在哪?用户得自己再点两下。

这事V哥第一反应是"是不是V哥没配对"。翻完官方文档才看明白: 从 6.1 起,系统把'扫码直达'这件事接好了大半,但'扫完落在哪一页'这件事,系统不知道,得你告诉它。

换句话说,入口是系统给的,落地是应用自己的活。把这两件分清楚,整套能力就顺了。

一、扫码直达到底是什么:系统扫,应用落

官方的描述很直白:开发者把域名注册到"扫码直达"服务后,用户通过 控制中心等系统级常驻入口 ,扫描应用的二维码、条形码,就能跳转到应用对应服务页,实现一步直达( 接入"扫码直达"服务 )。

V哥把整条链路拆成四步,画成一张业务流:

扫码直达业务流
| 步骤 | 谁来做 | 你写不写代码 |
| --- | --- | --- |
| ① 域名注册到扫码直达服务 | 你在 AGC + 开发者网站 | 不写,配 |
| ② 用户从系统扫码入口发起扫码 | 系统(控制中心等) | 不写 |
| ③ 系统解析码值、查到对应应用 | 系统 | 不写 |
| ④ 拉起应用、跳到对应服务页 | 系统拉起 + 你做路由 | 写 |

一眼看清了吧: 前③步都是系统的事,只有第④步的"落到哪个页",需要你接住码值再路由。

这里有个硬边界先说在前:扫码直达 仅支持中国境内 (香港特别行政区、澳门特别行政区、中国台湾除外)接入使用( 扫码直达 · 说明 )。如果你的应用做海外发行,这条链路在你那不生效,别硬等。

二、第一步:先把域名交给 App Linking

扫码直达到底靠什么把"码"和"你的应用"绑在一起?答案是 App Linking 。

官方的开发准备写得很明确:针对扫码直达, App Linking 是必选项 。你需要做四件事( 开发准备 · 仅针对扫码直达必选 ):

  • 在 AGC 控制台开通 App Linking 服务;

  • 在开发者网站上关联应用;

  • 在 App Linking 中配置二维码、条形码关联的网址域名;

  • 在应用的 module.json5 里关联这个域名。

  • 只能用 HTTPS 网址 。App Linking 当前仅支持 HTTPS,HTTP 域名直接不被接受。

  • 不能用自动签名 。官方明确:接入 App Linking 不能使用 DevEco 的自动签名功能,必须手动签名。第一次V哥卡在这半天,编译能过、扫码不跳,最后发现是签名方式不对。

  • 应用未安装时,码值对应的网页也得准备好 。用户手机没装你的应用,系统会拉起浏览器打开那个 HTTPS 页面——这是你"沉默获客"的兜底。

V哥的判断就一句: 域名是门票,App Linking 是那条门缝。门缝没开,后面再怎么写路由都是空转。

顺带说一句为什么这件事值得做:扫码直达的入口是系统级的常驻入口(控制中心等),比你在应用里自己塞一个扫码按钮浅得多。用户不用先打开你的 App、再找扫码入口,而是"系统一拍、直接落到服务页"。对拉新和复访来说,这条路径省掉的就是那两下点击——而这恰恰是最容易流失的地方。所以域名这一步,别嫌配起来麻烦。

三、第二步:在 EntryAbility 接住码值

系统拉起应用时,码值(那个 HTTPS 链接)会落在 Want 的 uri 字段里。你要做的,是在 EntryAbility 的两个入口都接住它: 冷启动走 onCreate ,热启动走 onNewWant 。

下面是自写的完整示例,把接住码值、再跳页的逻辑收在 routeByUri 一处:

import
{
UIAbility
,
Want
}
from
'@kit.AbilityKit'
;
import
{
BusinessError
}
from
'@kit.BasicServicesKit'
;
import
{ hilog }
from
'@kit.PerformanceAnalysisKit'
;
import
{ router,
window
}
from
'@kit.ArkUI'
;
export
default
class
EntryAbility
extends
UIAbility
{
private
uiContext?:
UIContext
;
onCreate
(
want
:
Want
):
void
{
this
.
routeByUri
(want);
  }
onNewWant
(
want
:
Want
):
void
{
this
.
routeByUri
(want);
  }
onWindowStageCreate
(
windowStage
:
window
.
WindowStage
):
void
{
    windowStage.
loadContent
(
'pages/Index'
);
    windowStage.
getMainWindow
().
then
(
(
win:
window
.Window
) =>
{
this
.
uiContext
= win.
getUIContext
();
    });
  }
private
routeByUri
(
want
:
Want
):
void
{
const
uri
:
string
|
undefined
= want?.
uri
;
if
(!uri) {
return
;
    }
const
target
:
string
=
ScanRouter
.
match
(uri);
if
(
this
.
uiContext
) {
const
state
: router.
RouterState
=
this
.
uiContext
.
getRouter
().
getState
();
if
(state && state.
name
!==
'Access'
) {
this
.
uiContext
.
getRouter
().
pushUrl
({
url
: target }).
catch
(
(
err: BusinessError
) =>
{
          hilog.
error
(
0x0001
,
'[ScanDirect]'
,
`路由失败 code:
${err.code}
`
);
        });
      }
    }
  }
}
  • 冷、热启动都接 :只写 onCreate ,应用本来就在后台时再扫一次码,你收不到第二次——因为走的是 onNewWant 。这个坑很隐蔽,不报错,只是"第二次扫码没反应"。

  • uiContext 异步拿到 : getMainWindow() 是 Promise,页面没加载完时 uiContext 还是空的,直接路由会空指针。教训是路由动作要等 uiContext 就绪。

  • 已经在目标页就别压栈 :不加这个判断,用户连扫两次,回退键要按好几下才能出去。

四、第三步:把码值收口成一张路由表

接住 uri 之后,最忌讳的就是"在 ability 里写一堆 if-else 判断路径"。码一多,逻辑就糊了。

V哥的做法是把"路径前缀 → 目标页"抽成一张规则表,集中维护:

import
{ hilog }
from
'@kit.PerformanceAnalysisKit'
;
import
{ url }
from
'@kit.ArkTS'
;
interface
RouteRule
{
pattern
:
string
;
page
:
string
;
desc
:
string
;
}
export
class
ScanRouter
{
private
static
rules
:
RouteRule
[] = [
    {
pattern
:
'/scan/pay'
,
page
:
'pages/Pay'
,
desc
:
'扫支付码 → 支付页'
},
    {
pattern
:
'/scan/order'
,
page
:
'pages/OrderDetail'
,
desc
:
'扫订单码 → 订单详情'
},
    {
pattern
:
'/scan/coupon'
,
page
:
'pages/Coupon'
,
desc
:
'扫券码 → 领券页'
},
  ];
static
match
(
uri
:
string
):
string
{
try
{
const
path
:
string
=
new
url.
URL
(uri).
pathname
;
for
(
const
rule
of
ScanRouter
.
rules
) {
if
(path.
startsWith
(rule.
pattern
)) {
return
rule.
page
;
        }
      }
    }
catch
(err) {
hilog.
error
(
0x0001
,
'[ScanDirect]'
,
`URI 解析异常:
${err}
`
);
    }
return
'pages/Index'
;
  }
}

把路由收口成表,好处是: 新增一种码,只改这张表,不动 ability。 这是工程上最划算的一笔。

扫码直达三步与应用侧职责

五、两个验证标准:装了跳履约页,没装跳网页

写完代码,别急着上线。官方给了两条验收标准,V哥建议你逐条对着查( 开发后验证 ):

| 标准 | 类型 | 你在验证什么 |
| --- | --- | --- |
| 应用已安装跳转体验 | 规则(必须满足) | 扫支付码跳到 支付页 ,不是首页 |
| 应用未安装跳转体验 | 建议 | 系统拉起浏览器,打开码值对应的网页 |
扫码直达两条验收标准

第一条是硬指标。V哥那个朋友的问题,恰恰就是扫完停在首页——他压根没做路由,URI 到了 Want 里就被忽略了。

V哥的铁律:履约页不是首页。 扫支付码,用户要的是支付,不是你的启动页。断在首页,就是断在体验上。

第二条是兜底。没装应用的用户,扫了你的码,应该被引到网页完成动作或下载——这条做不好,等于白白浪费一次触达。

六、6.1 的增强与边界

扫码直达本身依赖系统路由,应用侧改动不大。但 6.1 在 Scan Kit 上确实加了料,和你做扫码相关功能时能用上( Scan Kit 开发详解 ):

  • 默认界面扫码标题动态适配 : ScanOptions 里把 scanTypes 限定成单一制式(如只 QR_CODE ),系统扫码页标题会自动变成"扫描二维码"或"扫描条形码"。

  • Wearable 全支持 :6.1 起,带后置相机的穿戴设备也能用默认/自定义界面扫码。

  • 复杂场景算法加固 :曲面码、小角度码、污损码、远距离小码识别率提升。

但要把话说清楚: 这些是 Scan Kit 的增强,不是扫码直达的增强。 扫码直达的核心是"系统扫、应用落"的路由分发,应用侧那三步(注册域名、接住码值、路由履约页)在 6.1 的主线上没变。别把两件事混成一团去讲。

还有一个边界提醒:扫码直达要求中国境内,且 必须真机验证 ——模拟器不支持相机相关扫码能力,图像识码部分可模拟器调试,完整链路必须以真机实测为准( Scan Kit · 支持设备 )。

七、上线自检清单

把上面几点整理成一份可以贴进 PR 描述的清单:

  • 域名已在 AGC 开通 App Linking,并配置到扫码直达服务了吗?

  • module.json5 里关联了正确的域名吗?

  • 用的是 HTTPS 域名吗?(HTTP 不被接受)

  • 用的是 手动签名 吗?(自动签名会导致扫码不跳)

  • EntryAbility 的 onCreate 和 onNewWant 都 接住了 want.uri 吗?

  • 路由动作等 uiContext 就绪后才执行吗?

  • 码值 → 页面的映射收口在一张路由表里了吗?还是散落的 if-else?

  • 扫支付码 / 订单码,跳的是 履约页 而不是首页吗?

  • 应用未安装时,码值对应的网页能正常打开吗?

  • 连续扫码会不会重复压栈(已在目标页不再 push)?

  • 中国境内以外发行的版本,有降级方案吗(此能力不生效)?

  • 在 真机 上用控制中心扫码入口完整走通一遍了吗?

参考与出处

本文涉及的事实性信息(API 名称、枚举取值、版本号、官方约束)来自以下官方文档,文中的结构、代码示例、决策流程与自检清单为本人整理编写:

  • 接入"扫码直达"服务

  • Scan Kit(统一扫码服务)· 开发准备

  • Scan Kit(统一扫码服务)开发详解

  • App Linking 接入指导

  • 统一扫码服务(ArkTS)Codelab

最后一句 :扫码直达真正难的不是代码——满打满算就三步。难的是 把"系统扫、应用落"这件事分清楚 :门票(域名)交给 App Linking,接住码值写进 EntryAbility,路由履约页收成一张表。前三件做对,用户一扫就到;少一件,用户就停在首页。


转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:Juejin HarmonyOS

原创地址:https://juejin.cn/post/7685633346229125147

原文作者:威哥爱编程;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-08-02

  • 博文量
    36
  • 访问量
    35635