首发于华为开发者论坛:https://developer.huawei.com/consumer/cn/blog/topic/03225208468280132

错误码 13「卡片与快照不符合要求」这句提示,会让你一直去改卡片配置。改错方向了:缺的是包里的 pack.res——而它有没有被打进包,取决于你工程根有没有一个叫 EntryCard/ 的目录。本地编译、签名、安装全程不报错,因为本地根本不校验这一项。

我反复改的是 form_config.json,错的根本不是它

那是一个带 FormExtensionAbility 的元服务。包在本地编译、签名、装机全都正常,一传 AGC 解析就报 13。我当时以为是卡片本身配置有问题——form_config.json 写错了、尺寸不支持之类——于是反复改配置。本地编译一直是过的,传上去一直报 13。

接着想去搜官方文档,以为总有一节讲这个。搜不到,社区也几乎没有可用的中文资料。

转机是重新读那句报错:错误码 13 说的不是"卡片",是"快照"。AGC 解析 .app 的时候,要求每张卡片有同尺寸的快照,快照装在包里一个叫 pack.res 的文件里。回头解包看本地这个包——里面根本没有 pack.res。

pack.res 有没有,取决于一个目录存不存在

顺着 pack.res 往回找,在 hvigor 的任务源码里看到了机制(逐字,取自 tools/hvigor/hvigor-ohos-plugin/src/tasks/generate-pack-res.js):

class GeneratePackRes extends BasePackAppTask {
  constructor(e, s) {
    super(e, s, Task.GeneratePackRes),
    this.needPackRes && (this.packResCommand = new PackingToolOptions()
      .addCalledJarFile(this.packageTool).addMode("res")
      .addEntryCardPath(this.entryCardDir)     // ← 机制就在这一行
      .addPackInfoPath(this.packInfoPath).addOutPath(this.packResPath).force(!0).build())
  }
}

GeneratePackRes 只在 needPackRes 成立时才执行,而它吃的是工程根的 EntryCard/ 目录。目录不存在,任务不跑,包里没有 pack.res,AGC 解析时找不到快照,报 13。这条链每一环都干净利落,只是没有一环会在本地报错——校验发生在上传解析那一步,你在本地怎么编译都撞不到它。

目录怎么建、快照图从哪来

在工程根建这个:

EntryCard/entry/base/snapshot/widget-2x2.png

命名与层级规则都能在打包工具链的校验字符串里坐实(逐字,取自 toolchains/lib/app_packing_tool.jar):

The level-1 directory name must be EntryCard, current is
checkContain2x2EntryCard: file is not exist.
, correct format example is formName-2x2.png.

一级目录必须叫 EntryCard,严格大小写;第四级必须叫 snapshot;中间两级不强校验,惯例写模块名和 base。里面放 PNG,非 PNG 会报 No image in PNG format,.DS_Store 会被自动忽略。必须含 2x2 快照。文件名强制 formName-2x2.png——form_config.json 里那张卡的 name,加 -,加尺寸。文件名写错倒是本地打包就报、不用等 AGC:Invalid resource file name: xxx, correct format example is formName-2x2.png。

快照图不用画。把卡片装上真机、加到桌面、截屏,把卡片本体裁出来,往内收几像素去掉壁纸残留,存成 PNG。这样快照和真卡视觉 1:1,审核比对挑不出差别。

顺带一句,真机上给元服务加桌的路径和主 App 不一样:是在元服务运行中点右上胶囊的 ::,进 Add widget,从预览页添加至桌面——不是长按桌面图标。

判据是包里有没有那个文件,不是"我建了目录"

unzip -l <出包>.app | grep pack.res

必须看到 pack.res,体积大概几十 KB,那就是快照。看不到就说明 EntryCard/ 没被拾取,别传。这里必须解包验,因为目录名大小写错一个字母,任务照样不触发、照样不报错——"我建了目录"和"包里有 pack.res"之间,隔着一次静默失败的机会。

快照尺寸、空目录,和这篇管不到的事

快照尺寸不苛求,实测 412×403 都过了,别以为必须精确等于卡片规格的像素。这一套只有带卡片的包才需要:不带 FormExtensionAbility 的元服务没有这一步,建个空的 EntryCard/ 反而会撞上 EntryCard has no related snapshot。还有个微妙的地方——二三级目录名不强校验,所以照抄目录结构的人能过,但不知道哪一级是硬的。硬的只有第一级和第四级。

最后,这篇只解决"包传得上去"。卡片本身的合规面——免解锁可见、敏感信息脱敏——是另一件事,别混在一起。


这是《鸿蒙开发踩坑实录》第 7 篇。这条规则是从工具链里挖出来的,后来这种挖法本身长成了我的一个方法。

本文由作者与 AI 协作整理,事实经作者核验。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐