ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

鸿蒙上架卡审核?用多目标构建实现渐进式发布

鸿蒙上架卡审核?用多目标构建实现渐进式发布 做鸿蒙应用上架你是不是也遇过这种磨人的情况核心功能都写完了却在权限审核那一步卡了两三周因为要电话权限、存储权限、悬浮窗权限每一项都要单独补充使用场景说明隐私政策再一润色等终于全部通过时产品热度已经过去了。我身边不少开发同行在 HarmonyOS NEXT 上架时都踩过类似的坑后来我们才意识到上架这件事不该是一条路走到黑而是可以拆成几步走用渐进式发布让每次审核都只面对“该阶段的必要权限”而支撑这一套发布节奏的核心能力就是多目标构建。这篇文章就把我实际摸索出来的配置方式、提审流程和踩坑记录一次性讲清楚适合正在准备上架、或者已经因为权限问题被驳回好几次的鸿蒙开发者参考。先说明一下叫法社区里有人把 HarmonyOS NEXT 直接叫 HarmonyOS 6也有人说 API 12 / 5.0.0(12)正文里我统一用 HarmonyOS NEXT本质都一样。多目标构建不是什么黑科技它就是把一个工程里不同的模块、权限、签名、版本号组合成多个“构建变体”你可以理解成同一款车出了标准版和高配版动力总成不一样但底盘和内饰是同一套。下面我按思路、配置、上架实战、踩坑排查四个部分来展开。1. 先把思路理清多目标构建为什么是渐进式发布的关键1.1 渐进式发布到底在解决什么问题很多团队把“上架”想简单了以为写完代码、打好包、传上去等着过审就行。真正跑过一遍你会发现卡住你的往往不是代码而是上架材料、权限合规、隐私政策这类“非代码因素”。尤其是权限审核应用市场对电话、短信、通讯录、精确定位、后台弹窗这类敏感权限盯得非常严你不仅要在代码里申请还要在后台提交详细的用途说明、隐私政策链接、甚至使用场景录屏少一样都可能被驳回。渐进式发布的思路很简单第一版先上一个“低权限基础版”只保留最核心、不需要敏感权限的功能快速通过审核、快速上架等基础版本跑稳了用户也有了一定反馈再以“版本更新”的方式提交第二个高权限完整版。这个过程不是耍小聪明绕过审核而是把合规风险分散到不同版本里让团队有时间补齐材料、优化功能。很多跨端、小程序团队已经习惯灰度发布但原生鸿蒙应用由于权限声明、包结构、签名证书等原因必须在构建层面就把不同版本拆清楚这就是多目标构建登场的时机。1.2 多目标构建不是简单的 debug/release 区分刚接触 DevEco Studio 的开发者很容易把多目标构建理解成“多一个构建模式”以为就是 debug 和 release 的事。实际上多目标构建是把“构建变体”这个概念从单一维度扩展成了多维度组合。每一个 target 都可以指定自己编译哪些 module、使用哪个签名配置、在 module.json5 里声明哪一组权限、生成多大的版本号甚至匹配哪一套资源目录。我打个比方单 target 构建像你去餐厅只点套餐套餐内容写死在菜单上区分只能靠“大份小份”多目标构建则像自助餐你可以自由组合主菜、配菜、饮品。在鸿蒙工程里一个 target 对应一条完整的产品线比如“商店版”“极速版”“内测版”它们来自同一个源码仓库但产出的 APK/HAP 结构完全不同。这也是渐进式发布最需要的能力——同一个应用不同版本阶段交出不同能力集合的包。1.3 为什么手动切换配置的“土办法”不靠谱有人可能会问我不用多目标构建手动改 module.json5 的权限声明、改版本号、改签名不也能实现先低权限后高权限吗理论上能实操中非常容易出事。我就见过有人差点把带电话权限的包发到线上原因是手动改配置时漏改了一个 module导致本该是纯净版的应用偷偷带着敏感权限。手动方案至少有四个问题第一权限声明是静态的审核人员看的是你提交产物的最终声明运行时代码里做开关改不了静态声明第二手动配置容易漏改错改特别是工程里有多个 module 时项目结构越复杂越危险第三签名证书、版本号、混淆配置等状态分散在一堆配置文件里手动切换无法保证一致性第四回归验证困难你没法快速产出一套“同一代码库下的 A/B 两个包”做对比测试。多目标构建把这些状态全部收敛到 build-profile.json5 和工程结构里一键切换消灭手动失误。2. 工程侧拆解多目标构建的配置与权限隔离2.1 一个典型的多目标工程结构长什么样在动手配置之前先看一眼典型工程目录知道每个文件是干嘛的后面调参才不会心里没底。AppScope/ ├── app.json5 entry/ // 完整版主模块 ├── src/main/module.json5 // 完整版权限声明、入口abilities build-profile.json5 // 多目标配置的核心 oh-package.json5如果你想做一个“精简版”和“完整版”两个目标更推荐直接创建两个模块比如entry和entry_lite。每个模块有自己的module.json5互不干扰权限声明天然隔离。这里有个重要的认知权限隔离的第一原则就是“不要试图在同一个模块里绕来绕去”而是让不同模块各自维护自己的声明。同一个模块共用一套 module.json5 的话你只能靠条件编译躲过代码逻辑但静态权限声明还是会被打进去所以模块隔离是基础。2.2 build-profile.json5 里的关键配置项在 DevEco Studio 里你可以通过File Project Structure Build Variants可视化地管理 targets但真正理解底层配置还是得看build-profile.json5。不同的 IDE 版本生成的注释和默认字段略有差异但核心结构类似下面是一个参考形态{ app: { signingConfigs: [ { name: common_signing, material: { certpath: distribution.cer, storePassword: ******, keyAlias: release_key, keyPassword: ******, profile: distribution.p7b, signAlg: SHA256withECDSA } } ], products: [ { name: product_all, signingConfig: common_signing, compatibleSdkVersion: 5.0.0(12), runtimeOS: HarmonyOS, buildOption: { strictMode: { caseSensitiveCheck: true } } } ], targets: [ { name: entry_lite, type: module, applyToProducts: [product_all], modules: [entry_lite] }, { name: entry_full, type: module, applyToProducts: [product_all], modules: [entry, feature_pay, feature_share] } ] }, modules: [ { name: entry, srcPath: ./entry, targets: [{ name: entry_full, applyToProducts: [product_all] }] }, { name: entry_lite, srcPath: ./entry_lite, targets: [{ name: entry_lite, applyToProducts: [product_all] }] } ] }重点看targets字段name是这个构建变体的名字数组里的modules决定这个 target 会编译哪些模块。比如完整版 target 带了feature_pay和feature_share精简版只带entry_lite从源头决定了功能范围。applyToProducts的意思是“这个 target 应用到哪个 product 上”product 可以理解为产品维度配置比如不同渠道、不同 SDK 版本。初级玩法下一个 product 挂多个 target 就够用了。2.3 权限隔离与条件编译的配合方式配置好多目标之后每个模块的module.json5里声明权限entry的 module.json5声明ohos.permission.READ_MEDIA、ohos.permission.GET_NETWORK_INFO、ohos.permission.INTERNET等完整权限。entry_lite的 module.json5只声明ohos.permission.INTERNET这种基础权限。这样打包出来的精简版安装到手机上系统层面就不会出现敏感权限的授权弹窗应用市场审核材料里也只展示基础权限列表审核压力小很多。代码逻辑层再配合条件编译把“完整版功能”和“精简版功能”隔离开。在 DevEco Studio 的构建选项里可以定义宏开关比如在完整版 target 的 buildOption 中配置buildOption: { define: { BUILD_FULL_VERSION: true } }然后代码中这样处理// 完整版才编译支付相关页面 ifdef BUILD_FULL_VERSION import { PayPage } from ../feature_pay/PayPage; endif条件编译的好处是构建时直接裁剪代码而不是运行时 if-else 判断精简包里连相关业务代码都不会出现体积和风险都更小。需要特别注意的是条件编译关键字和宏名称跟你 DevEco Studio 版本的模板有关建工程时可以先用它自带的示例试一下确认宏生效再大规模接入业务代码。2.4 签名证书与版本号的管理要点渐进式发布的本质还是同一个应用的多版本迭代所以多 target 必须使用同一个正式签名证书。鸿蒙应用商店在首次上架时会记录你的签名指纹后续所有更新包都必须用同一把证书签名否则上传阶段就会被判为“包名与签名不一致”。我在工程里只维护一份signingConfigs所有 target 共用这一个配置从源头避免签名漂移。版本号这里我有过一次教训。鸿蒙应用市场的版本判断逻辑和安卓类似versionCode必须递增versionName是展示用的版本名。如果你有两个 target建议给它们各自维护自己的版本递增线精简版从versionCode 1000001起步完整版从2000001起步。这样后续即使多 target 交叉发版也不会出现“低版本号覆盖高版本号”的问题。另外在 AGC 后台修改版本时系统对 versionCode 的校验非常严格如果上一个已上架版本是1000002下一个提交版本必须是1000003或更大哪怕你换了一个 target 也一样所以不要让两个 target 共用同一条 versionCode 线。3. 上架实战从构建产物到 AGC 后台的完整流程3.1 构建目标产物App 包还是 HAP 包配置好 targets 之后构建操作在 DevEco Studio 里非常直观。IDE 顶部菜单Build下会有Build Hap(s)和Build App(s)两个选项区别在于 HAP 是单个模块的产物App 包后缀.app是把参与构建的所有 HAP、pack.info 等资源打包在一起的发布包。上架时我个人更推荐构建 App 包理由是 App 包包含了所有参与模块的 HAP上传 AGC 后后台能完整识别应用结构只传单个 HAP 容易在后续多模块更新时出现模块对不上的问题。构建前要确认当前激活的 target 是哪一个在Build Variants面板里每个 module 旁边都有 target 下拉列表切到entry_lite就会构建精简版切到entry_full就构建完整版。注意查看底部 Build 窗口的输出确认编译的是不是你想要的 target 名字。我就犯过迷糊切了 target 但忘了重新 Sync结果打出来的还是上一次的产物。3.2 首次上架精简版如何先行在 AppGallery ConnectAGC后台创建应用后第一步是把应用的基本信息填完整包括包名、分类、隐私政策链接等。这里的包名必须和工程里app.json5配置的 bundleName 完全一致否则上传包会直接报错。上传构建出来的.app包后台会自动解析版本号和权限信息。在“版本信息”页面你会看到权限列表里只有基础权限对应的“敏感权限”一栏是空的这就是我们想要的效果首版只聚焦基础体验审核团队需要审查的范围被压缩到了最小。把隐私政策、应用说明、截图、软著看应用类型要求都按后台提示补齐提交审核。正常情况下精简版的审核速度会比完整版快很多因为没有什么敏感权限需要单独核实。3.3 后续更新用高权限版本渐进放开等精简版正式上线用户反馈和数据链路都正常了再进行第二步。在 DevEco Studio 中切到完整版 target确认版本号递增构建新的.app包。在 AGC 后台点击“添加新版本”上传完整版包这时你会看到权限列表里多出了电话、媒体、定位等敏感权限。后台会要求你补充这些权限的使用说明、触发场景、是否涉及第三方共享等信息。这里有一个实操技巧提前做好权限用途说明文档比如“为什么需要读取媒体文件——用于用户上传头像”在首次提交精简版时就可以准备好等完整版提审时直接粘贴能省出至少两天的准备时间。完整版更新审核通过后应用市场会自动把已有用户升级到新版本新用户下载的也是完整版渐进式发布闭环完成。3.4 和分阶段发布/灰度发布叠加使用你会发现渐进式发布和 AGC 后台的“分阶段发布”是完美互补的。多目标构建解决的是“不同能力集合”的问题分阶段发布解决的是“流量圈层”的问题。我见过一个团队的做法完整版提交审核通过后先在后台设置按 5% 的比例发布观察崩溃率和用户反馈确认没问题再逐步放量到 50%、100%。如果你做的是工具类应用这种“能力分批流量分批”的组合拳非常值得抄作业。另外提醒一点分阶段发布是按比例灰度不是按用户群细分如果你需要精确到某个用户组还得配合服务端路由逻辑。多目标构建和灰度发布是两条独立链路不要混在一起设计不然排查问题时很难定位到底是谁的问题。4. 上架期间我踩过的坑与排查经验4.1 多目标构建常见问题速查表现象原因解决办法上传 App 包提示包名不一致bundleName 与 AGC 后台创建应用时的包名不一致检查 app.json5 的 bundleName保持与 AGC 后台一致更新版本时提示“版本号无效或未递增”两个 target 共用了同一条 versionCode 线每个 target 维护独立版本号提交前核对上一线上版本号审核被拒原因是未声明却申请了敏感权限某个 module.json5 里残留完整版权限声明检查所有参与构建的 module确保精简版 target 只包含基础权限构建产物没有包含期望的 feature 模块当前 target 的 modules 字段缺模块到 build-profile.json5 的 targets 配置中补全 modules条件编译代码没有生效宏定义没有配置到对应 target 的 buildOption在构建选项里配置 define并用示例代码验证签名证书校验失败多个 target 用了不同签名证书统一使用同一份签名配置重新签名打包完整版更新后用户无法覆盖安装versionCode 小于已上架版本新版本 versionCode 必须大于所有已发布版本的最大值4.2 案例一干净的基础版却带着敏感权限我第一次做多目标构建时自信满满地把精简版提审结果审核邮件说应用声明了读取媒体文件权限但缺少对应用途说明。我当时很疑惑明明entry_lite的 module.json5 里只写了 INTERNET。排查了很久最后发现根因是构建产物里打进了另一个静态库的 module.json5那个库是完整版支付模块依赖的而我在配置modules时把完整版的feature_pay也加进了精简版 target。这个坑提醒所有人配置 targets 时要顺着依赖关系穷举一遍“会参与编译的模块有哪些”不只是你自己写的modules列表。用Build Build Hap(s)构建后解包查看产物中的 module.json5 权限声明确认干净再提审不要嫌麻烦。4.3 案例二条件编译宏不生效页面重复注册另一个印象深刻的坑是在完整版里加了支付模块但精简版启动时居然也注册了支付路由明明代码里写了ifdef FULL_VERSION包住。后来发现我在工程级 buildOption 里定义了宏但 DevEco Studio 的 target 构建体系里条件编译宏是按 target 粒度解析的我配置在了默认产品级没用。把宏定义写进完整版 target 的 buildOption 里重新 Sync 后精简版包里的路由代码才彻底消失。这类问题排查思路很简单分别构建两个 target 的产物用解包工具看看对应代码是否真的被裁剪掉了。另外一个技巧是在精简版的启动日志里打一个构建标记比如console.info([BUILD_MODEL] lite)完整版打full线上排查包版本时一眼就知道用户装的是哪条产品线。4.4 关于跨端框架和小游戏上架的一些实话有同行问我自己用 uni-app 做了应用能不能上架鸿蒙能但这里有个认知要摆正跨端框架的上架流程与原生应用完全一致审核不会因为你是跨端项目就降低标准。你的产物本质上还是 HAP 包商店审核人员同样会查权限、查隐私政策、查应用内容这些合规工作一项都跑不掉。多目标构建这套思路对跨端项目也有借鉴意义只是配置对象变成了你最终生成的 HAP 工程而不是你的源码工程。至于 AI 开发小游戏能不能上架答案是能但小游戏通常用 Cocos、Laya 或 Unity 引擎出包这类引擎有自己的构建体系一般用不上 DevEco Studio 的多目标构建。如果你是用 ArkUI/ArkTS 写的轻量游戏那完全可以套用我上面介绍的隔离思路比如首版只做单机模式后续版本再解锁联网对战这样首版审核时就不需要申报网络游戏相关资质发布节奏会从容很多。5. 最后分享一点我的实际体会多目标构建不是让开发者想办法“偷工减料”它的价值在于把上架这个本来必须一口气做完的事情拆成了可以分阶段完成的小目标。我在 HarmonyOS NEXT 上架项目里实践了小半年最深的感受是工程配置本身花不了多少时间真正花时间的是版本管理纪律和权限合规意识。两个 target 足够绝大多数应用使用一个精简版、一个完整版除非你确实需要内测能力版否则 target 不是越多越好每多一个 target就意味着多一条构建验证成本。先想清楚哪些功能必须首发哪些可以放到更新版本里再去动手配置多目标构建你会发现自己对发布节奏的控制力完全不一样。
返回列表