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

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


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

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

他说:"这码白做了。"

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

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


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

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

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

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

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

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


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

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

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

  1. 在 AGC 控制台开通 App Linking 服务;
  2. 在开发者网站上关联应用;
  3. 在 App Linking 中配置二维码、条形码关联的网址域名;
  4. 在应用的 module.json5 里关联这个域名。

三个V哥自己踩过的坑,提前说:

  • 只能用 HTTPS 网址。App Linking 当前仅支持 HTTPS,HTTP 域名直接不被接受。
  • 不能用自动签名。官方明确:接入 App Linking 不能使用 DevEco 的自动签名功能,必须手动签名。第一次V哥卡在这半天,编译能过、扫码不跳,最后发现是签名方式不对。
  • 应用未安装时,码值对应的网页也得准备好。用户手机没装你的应用,系统会拉起浏览器打开那个 HTTPS 页面------这是你"沉默获客"的兜底。

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

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


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

这一步才是真正要写代码的地方。

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

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

typescript 复制代码
// entryability/EntryAbility.ets
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;

  // 冷启动:系统扫码入口拉起时,码值经 App Linking 落在 want.uri
  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();
    });
  }

  // 把"码值 → 页面"的映射收口在一处,别散落到各 ability
  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}`);
        });
      }
    }
  }
}

这里有三个V哥自己加的细节,值得单说:

  • 冷、热启动都接 :只写 onCreate,应用本来就在后台时再扫一次码,你收不到第二次------因为走的是 onNewWant。这个坑很隐蔽,不报错,只是"第二次扫码没反应"。
  • uiContext 异步拿到getMainWindow() 是 Promise,页面没加载完时 uiContext 还是空的,直接路由会空指针。教训是路由动作要等 uiContext 就绪。
  • 已经在目标页就别压栈:不加这个判断,用户连扫两次,回退键要按好几下才能出去。

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

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

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

typescript 复制代码
// common/ScanRouter.ets
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 不被接受)
  • 用的是手动签名吗?(自动签名会导致扫码不跳)
  • EntryAbilityonCreateonNewWant 接住了 want.uri 吗?
  • 路由动作等 uiContext 就绪后才执行吗?
  • 码值 → 页面的映射收口在一张路由表里了吗?还是散落的 if-else?
  • 扫支付码 / 订单码,跳的是履约页而不是首页吗?
  • 应用未安装时,码值对应的网页能正常打开吗?
  • 连续扫码会不会重复压栈(已在目标页不再 push)?
  • 中国境内以外发行的版本,有降级方案吗(此能力不生效)?
  • 真机上用控制中心扫码入口完整走通一遍了吗?

参考与出处

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


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

相关推荐
威哥爱编程1 小时前
HarmonyOS 6.0 智感握姿实战:一道安检门、五态分诊、一静一响两个坑
华为·harmonyos·arkts
李游Leo2 小时前
HarmonyOS 7 音频与媒体控制实战 02:实现系统音频内录与状态控制
harmonyos
李游Leo2 小时前
HarmonyOS 7 音频与媒体控制实战 05:排查播放无声、卡顿和杂音问题
harmonyos
大雷神2 小时前
【共创稿事节】HarmonyOS ArkGraphics 3D 实操:用 GLB 节点与 PBR 材质打造智能音箱选配器
harmonyos
贾伟康11 小时前
【HarmonyOS 7新能力|020】LazyLayoutAlgorithm入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·lazylayout
梦想不只是梦与想12 小时前
鸿蒙 邀请测试:发布测试版本
harmonyos·appgallery 邀请测试·邀请测试
Winner_hwx13 小时前
华为ICT大赛备赛复习1
服务器·网络·华为
马剑威(威哥爱编程)14 小时前
【共创稿事节】HarmonyOS 7 应用 Skill 化实战:从“被打开“到“被调用“,把功能递进系统意图分发池
pytorch·深度学习·harmonyos
HarmonyOS_SDK16 小时前
HarmonyOS Push Kit 自分类权益 Skill,助力提升权益申请通过率
harmonyos