都 2025 了,还不会一键发版?——「鸿蒙应用打包、签名与发布」这点事儿,今天一次讲透好不好!

举报
bug菌 发表于 2025/11/01 20:11:33 2025/11/01
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8 前言打工人心声:写功能很快乐,发版像过独木桥。打包、签名、上架、各种校...

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

打工人心声:写功能很快乐,发版像过独木桥。打包、签名、上架、各种校验与合规,一路红线等着你踩。别慌,这篇用工程视角 + 实操脚本 + 清单化检查,把鸿蒙(HarmonyOS / OpenHarmony)应用的打包、签名与发布从“玄学”掰成“流程”。读完你能把“能跑”稳定地变成“能上架”。还得有点人话与幽默——不然谁看呀🙂


你将收获什么

  • HAP 与 APP 包结构:它俩是什么关系、目录里都装了些啥
  • 签名机制:证书、Profile、调试/发布签名、离线/CI 签名姿势
  • 发布流程与规范:版本、权限、隐私、包体、截图与合规自查
  • 脚本化落地:Hvigor/CLI 打包、签名与产物校验的小样例
  • Checklist:能拯救你凌晨 Re-Upload 的“最后 10 分钟”

一、先把名词扣稳:HAP 与 APP 到底啥关系?

1)一句话版

  • HAP(Harmony Ability Package)模块级安装包。一个 HAP 对应一个模块(如 entryfeature_x)。
  • APP(App Pack)应用级打包产物,把一个或多个 HAP(含按架构/按特性拆分的 HAP)再装进一个壳,用于分发与安装。

2)结构示意(精简)

HAP 内部(模块包):

myapp-entry-default.hap
├─ module.json5              # 模块清单(名称、入口、权限、设备类型、能力)
├─ resources/                # 资源(多语言/分辨率/深浅色)
├─ ets/                      # ArkTS/ETS 编译产物(或 js/so 等)
├─ libs/
│  ├─ arm64-v8a/*.so
│  └─ riscv64/*.so
├─ assets/                   # 运行时资源(不参与编译,随包分发)
├─ pack.info                 # 打包信息(构建元数据)
└─ signature/                # 签名块(发布签名或调试签名)

APP 内部(应用包):

myapp-1.4.2-release.app
├─ HAP/
│  ├─ myapp-entry-default.hap
│  └─ myapp-feature-share.hap
├─ app.json5                 # 应用层清单(bundleName、版本、icon 等)
├─ pack.info
└─ signature/                # 应用层签名(与证书/配置文件绑定)

形象点讲:HAP 是积木块APP 是装满积木块的盒子。商店分发通常用 APP;独立分发某个特性/形态时,也可能投放单 HAP(视商店策略而定)。


二、构建:Hvigor/DevEco 一把梭,别手剥洋葱

下面示例把「可复制粘贴」放在第一位——你可以放进项目 scripts/ 里直接跑,CI 上也好改。

1)项目关键清单

app.json5(应用级)

  • bundleName:全局唯一(反域名);
  • versioncode(整数,自增)与 name(人类可读)。
// app.json5(片段)
{
  "app": {
    "bundleName": "com.acme.supernotes",
    "vendor": "Acme Inc.",
    "version": { "code": 42, "name": "1.4.2" },
    "icon": "$media:app_icon",
    "label": "$string:app_name"
  }
}

module.json5(模块级)

  • nametypeentry/feature/har 等);
  • deviceTypesphone/tablet/car/wearable…);
  • abilitiesUIAbility 等)、requestPermissions(用途要对齐隐私描述)。
// module.json5(片段)
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": [ "phone", "tablet" ],
    "abilities": [{
      "name": "MainAbility",
      "srcEntry": "./ets/entryability/EntryAbility.ets",
      "label": "$string:app_name",
      "icon": "$media:app_icon"
    }],
    "requestPermissions": [
      { "name": "ohos.permission.CAMERA", "reason": "$string:perm_camera" },
      { "name": "ohos.permission.LOCATION", "reason": "$string:perm_location" }
    ]
  }
}

2)本地打包(Release)

  • DevEco StudioBuild > Build APP(s) 选择 Release
  • Hvigor CLI(推荐拉到 CI):
# 1) 安装依赖(ohpm)
ohpm install

# 2) 产出 Release HAP(多模块会各自生成 HAP)
./hvigorw assembleRelease

# 3) 打 APP(把多个 HAP 合并为 APP)
./hvigorw app -p product=release
# 产物通常在 ./build/default/outputs/

小贴士:本地打包前,先 Clean Project,再 Rebuild,避免老资源卡在缓存里“闹鬼”。


三、签名机制:证书 + Profile + 签名块,三角形缺一不可

1)你需要哪些东西?

  • 应用证书(.p12 或等价格式):包含私钥,用于对包签名。
  • Profile(调试/发布配置文件):绑定证书、公钥、包名、设备/分发范围等,告诉系统“这包能在什么环境跑”。
  • 签名参数:别名(alias)、签名算法、证书链、时间戳等。

调试发布用的 Profile 与证书通常分开。调试包能装在测试设备,上架必须用发布证书 + 发布 Profile

2)在工程里配置签名(示例)

signingConfigs(hvigor 配置片段)

文件路径因模板不同而异,核心是给 release 指定证书与 profile。

// hvigor/ohos/signingConfigs.js(示例)
module.exports = {
  debug: {
    storeFile: 'signing/debug/my_debug_cert.p12',
    storePassword: process.env.DEBUG_STORE_PWD,
    keyAlias: 'debug_key',
    keyPassword: process.env.DEBUG_KEY_PWD,
    profile: 'signing/debug/debug-profile.p7b'
  },
  release: {
    storeFile: 'signing/release/my_release_cert.p12',
    storePassword: process.env.RELEASE_STORE_PWD,
    keyAlias: 'release_key',
    keyPassword: process.env.RELEASE_KEY_PWD,
    profile: 'signing/release/release-profile.p7b'
  }
}

hvigorfile.js 里引用:

const signing = require('./ohos/signingConfigs');
ohosApp({
  signingConfigs: signing,
  // 其他构建参数……
});

环境变量(如 RELEASE_STORE_PWD不要写死在仓库;CI 用“机密变量”注入即可。

3)CI 离线签名流程(常见做法)

  1. 构建未签名 HAP/APP(可通过构建参数输出 unsigned 包);
  2. 签名 Job 拉取证书与 profile(CI 安全库),调用签名工具对产物签名;
  3. 验签(校验签名块与证书链);
  4. 产物上传到制品库或商店。

优点:开发机无需接触发布证书;证书权限集中、可审计。


四、发布前的“九连问”(市场发布规范 · 实操视角)

商店规则可能不断更新,但底层逻辑万变不离其宗。把这些点做扎实,扣分概率立刻下降。

1)元数据与版本

  • bundleName:不可和他人重名;一旦上架,后续版本必须相同
  • 版本号version.code 单调递增version.name 对用户友好即可。
  • 渠道标识:若有多渠道包,请勿用不同 bundleName 伪装渠道(容易被拒)。

2)权限与隐私

  • 只申请用得上的权限;弹窗按场景触发(不要开屏就要定位/相机)。
  • 隐私政策:应用内可达(设置—隐私);对每项权限写明用途、采集范围、保留期、撤回方式。
  • 第三方 SDK 列表:如用到统计/广告/分享,需在说明中列出并做最小化配置。

3)适配与包体

  • 设备类型deviceTypes 与实际设计一致;不支持就别勾(车机/可穿戴可分 HAP)。
  • ABI:仅包含你支持的架构(比如 arm64-v8a);别把全集都塞进来。
  • 包体限制:大二进制(模型、视频)尽量拆到 资源包/在线加载;图片/动画做 WebP/压缩

4)内容与展示

  • 图标/截图/描述:风格一致、清晰、勿含第三方商标(除非授权)。
  • 评级/分级:如涉及用户生成内容(UGC),说明审核与举报机制
  • 无障碍:关键流程可达、字号与对比度合规,键盘/读屏可用(加分项)。

5)稳定性与性能

  • 首启 ≤ 2s(主页面可交互):Skeleton + 懒加载。
  • 崩溃率:灰度前先过“真机回归 + 设备矩阵”;日志脱敏
  • 功耗:后台场景停用长连接/定位/传感器,前后台策略对齐申报。

一句话:把“隐私、权限、内容、稳定”四条线拉直,提审就顺滑。


五、把流程脚本化:从“一次点错”变成“永不出错”

1)一键打包与签名(示例脚本)

#!/usr/bin/env bash
# scripts/build_release.sh
set -euo pipefail

export RELEASE_STORE_PWD="${RELEASE_STORE_PWD:?missing}"
export RELEASE_KEY_PWD="${RELEASE_KEY_PWD:?missing}"

echo "[1/4] Install deps"
ohpm install

echo "[2/4] Build HAPs (release)"
./hvigorw assembleRelease

echo "[3/4] Pack APP"
./hvigorw app -p product=release

OUT="./build/default/outputs/app/release"
APP=$(ls "$OUT"/*.app | head -n1)

echo "[4/4] Verify signature"
hap-tool verify --file "$APP"  # 示意命令,按你使用的工具替换

echo "✅ Done: $APP"

2)产物体检(自查脚本)

#!/usr/bin/env node
// scripts/app_lint.js
const fs = require('fs');
const path = process.argv[2];
if (!path || !fs.existsSync(path)) {
  console.error('Usage: node app_lint.js <path-to-app>');
  process.exit(1);
}
// 伪检查:你可以解包后校验以下字段
const checklist = [
  'bundleName present',
  'version.code monotonic',
  'module.json5 requestPermissions reason provided',
  'contains only expected ABIs',
  'assets size under threshold',
  'signature block exists'
];
console.log('Running lint on', path);
for (const item of checklist) console.log(' •', item);
console.log('✅ Lint passed (demo)');

真正在 CI 里,你可以把 APP 解包成临时目录,读取 app.json5/module.json5静态校验;同时跑一个 devices-smoke(真机自动冒烟)确保安装、启动、主要路径可用。


六、实操问与答(坑位警示标语)

Q1:同一个应用多个 HAP 怎么取舍?
A:按功能/形态拆entry.hap 放主 UIAbility;独立功能(如分享、打印)做 feature.hap,按 deviceTypes 精准投放。别用 HAP 当“多渠道”

Q2:签名密钥丢了?
A:这不是“如果”,是“何时”。立刻停更旧密钥对应的线上版本,申请新证书与 Profile,发布新包并迁移。务必在团队与 CI 做密钥托管轮换计划

Q3:调试包能上架吗?
A:不行。调试 Profile 只允许在指定设备安装。上架必须走发布证书 + 发布 Profile,并通过商店的静态/动态检查。

Q4:多设备(平板/车机)要做多个包吗?
A:看功能是否差异巨大。常见做法是同一应用下多 HAP,每个 HAP 设定不同 deviceTypes,资源与布局做自适配;极端差异再考虑分应用。


七、发布前最终 Checklist(打印贴墙!)

元信息

  • [ ] bundleName 固定 & 唯一
  • [ ] version.code 比上一个版本更大
  • [ ] icon/label 系列资源齐全(暗/亮、密度、圆角)

签名

  • [ ] 使用发布证书 + 发布 Profile
  • [ ] CI/本地签名一致可复现
  • [ ] 验签通过(证书链、时间戳、签名块)

权限与隐私

  • [ ] 仅保留必要权限requestPermissions 完整 reason
  • [ ] 应用内隐私政策可达,逐项对应权限用途
  • [ ] 第三方 SDK 名单与用途说明

包体/兼容

  • [ ] 仅包含需要的 ABI
  • [ ] 大资源做外置或按需下载
  • [ ] 真机冒烟通过(冷启动、主要流程、后台前台切换)

商店素材

  • [ ] 名称、简介、关键词不涉敏感词
  • [ ] 截图/视频和实际功能一致
  • [ ] 年龄分级、分类正确;UGC 有治理说明

结语:发布不是“临门一脚”,是“工程化终点站”

写到这,你应该已经能把HAP/APP 的关系说清楚,把签名从“玄学”拉回“配置”,把发布规范从“迷雾”变成“清单”。别忘了,真正让你发版变轻松的,不是今天运气好,而是流程脚本化 + 清单常态化 + 证书托管制度化
  下一次点下「提交审核」的时候,愿你心态稳得像早八地铁上的扶手:摇,但不慌。🚀

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。