14 KiB
mobile-uni 原生 App 打包
mobile-uni/ 采用 uni-app Vue 3 的 App-Plus 目标,同时保留 H5。App 不是将线上 H5 包进 WebView;前端资源通过 npm --prefix mobile-uni run build:app 编译,再由 HBuilderX 的自定义基座或云端打包生成 Android/iOS 原生安装包。
当前约定
- Android applicationId 与 iOS Bundle ID 预设为
com.yincheng.wygj。在首次签名或注册 App ID 前,发布负责人必须确认企业实际拥有该标识;变更时 Android、iOS 必须同步修改。 - App 直接请求
https://peilian.njzhmj.top/dev-api。不依赖 H5 开发服务器的/dev-apiproxy;地址是公开配置,不得在 App 包中放入短信、模型、签名或任何服务端密钥。 manifest.json只保留不含秘密的发布配置。.keystore、.p12、.mobileprovision与证书密码只能由发布负责人在 HBuilderX 云打包界面或受控 CI 秘密变量中提供,绝不能提交 Git。- Android 最低试点设备为 Android 10,
manifest.json显式固定targetSdkVersion=35,避免回落到 DCloud 默认 API 28 兼容模式;iOS 最低试点设备为 iOS 15。每次发版提升versionCode,再更新versionName。 - Android 设备信息与外部存储权限固定为启动时不申请;Camera/Record 模块仅在用户进入相应功能后走运行时授权。不要为了消除系统权限声明而删除实际使用的媒体模块,也不要恢复启动即申请。
- 当前编译链与本机 HBuilderX 5.22 对齐:GUI 产品版本为
5.22.2026071707,D:\HBuilderX\cli.exe version返回5.22.2026072503-alpha;@dcloudio/uni-app、@dcloudio/uni-app-plus、@dcloudio/uni-h5、@dcloudio/vite-plugin-uni均固定为3.0.0-alpha-5020220260725001。这是 HBuilderX/uni-app 编译器版本,不是 AndroidminSdkVersion。 - 四个 DCloud 编译包必须保持同一批次;否则 npm 版 uni-ui 的 easycom 解析可能落入不同的
uni-cli-shared实例,表现为<uni-forms>、<uni-easyinput>等组件无法解析。
本地验证与出包
npm --prefix mobile-uni run generate:app-assets
npm --prefix mobile-uni run verify:app-assets
npm --prefix mobile-uni run typecheck
npm --prefix mobile-uni run build:h5
npm --prefix mobile-uni run build:app
云打包完成后必须校验实际 APK,不能只看 HBuilderX 的“打包成功”:
npm --prefix mobile-uni run verify:android-apk
该命令默认校验 mobile-uni/dist/debug/android_debug.apk 自定义基座,包括包名、源码版本、targetSdkVersion、调试属性、单签名、APK Signature Scheme v2 和 SHA-256。脚本使用 HBuilderX app-safe-pack 内的只读 APK 工具;非默认安装目录可通过 -HBuilderHome 指定。
Android 内测包或正式 RC 使用版本化的 mobile-uni/.env 保存两个公开法务地址,确保 npm 和 HBuilderX 云打包得到同一配置。地址不是秘密,可由 PowerShell 环境变量覆盖;正式发布前仍须由公司法务签认正文:
Remove-Item Env:VITE_DEV_SMS_HINT_ENABLED -ErrorAction SilentlyContinue
Remove-Item Env:VITE_DEV_SMS_HINT_VALUE -ErrorAction SilentlyContinue
npm --prefix mobile-uni run configure:app-legal
npm --prefix mobile-uni run build:app
npm --prefix mobile-uni run verify:app-release
configure:app-legal 会校验 HTTPS、公网域名和两个地址互不相同,并从模板生成被 Git 忽略的 mobile-uni/src/androidPrivacy.json;其唯一职责是明确 prompt=none,不再提供启动原生确认。build:app 将该配置复制到 dist/build/app/androidPrivacy.json,并把项目根的 AndroidManifest.xml 与 nativeResources/android/res/xml/network_security_config.xml 同步到云打包输入目录。源码、编译产物和实际 APK 都纳入门禁。兼容别名 configure:app-privacy 暂时保留。verify:app-release 还会确认:
manifest.json使用useOriginalMsgbox=false,androidPrivacy.json使用prompt=none;- 登录页默认未勾选协议,服务协议与隐私政策链接来自本次 App 编译的
VITE_APP_TERMS_URL、VITE_APP_PRIVACY_URL; - 发送验证码和登录均先通过同一个
ensureLegalConsent()门禁; - 两个页面可通过公网 HTTPS 访问并包含可识别的协议正文;
VITE_DEV_SMS_HINT_ENABLED与VITE_DEV_SMS_HINT_VALUE均未进入发布环境;- 编译产物不含手机号、固定测试验证码、私钥或常见云端/API 令牌格式。
- Android 清单与网络安全配置均禁止明文 HTTP,并只信任系统证书。
登录页默认不勾选协议。协议地址缺失或不合规时,页面允许查看但禁止发送验证码和登录;测试验证码快捷提示只有开发环境同时显式设置 VITE_DEV_SMS_HINT_ENABLED=true 和本机 VITE_DEV_SMS_HINT_VALUE 才显示。源码不再内置固定验证码值。
- 用 HBuilderX 打开
mobile-uni,先生成 Android/iOS 自定义运行基座。标准基座不会加载当前的包名、权限、启动图或原生配置。 - 在真实 Android 与 iPhone 上验证手机号登录、录音并转写、TTS 播放、图片/视频/文件上传、附件下载、拒绝权限、前后台切换、刘海和底部安全区。
- Android 试点使用企业签名的正式 APK;上架渠道按渠道要求导出相应制品。iOS 使用企业 Apple Developer 账号的 Distribution 证书和 provisioning profile,先走 TestFlight。
标准基座可用于日常 JavaScript/WebView 兼容性调试,但不能替代自定义基座或签名包的权限、图标、启动图和原生配置验收。
HBuilderX 5.22 当前实测中,自定义调试基座不支持安心打包,新应用也不能再使用公共测试证书;调试基座改用 DCloud 云端证书并通过普通云打包生成,CLI 项目的产物位于 mobile-uni/dist/debug/android_debug.apk。该云端证书和调试 APK 不替代企业正式签名资产。
自定义基座 APK 只包含原生调试运行壳,业务 www 资源由 HBuilderX 真机运行时另行同步,因此不能要求登录页法务链接出现在基座 APK 内。可直接安装分发的 DCloud 云证书内测包必须使用非自定义基座打包,并用 dcloud-test 模式复核包内 prompt=none、app-service.js 的两个登录页地址和未勾选拦截:
& '.\mobile-uni\scripts\verify-android-apk.ps1' `
-ApkPath '.\mobile-uni\dist\debug\bangdao-0.1.13-dcloud-test.apk' `
-BuildKind dcloud-test
APK 门禁还会比较包内与当前 dist/build/app/app-service.js 的 SHA-256,避免用同版本号的旧包冒充当前源码,并在反编译结果中复查敏感文件、手机号、固定测试验证码、私钥和常见令牌格式;dcloud-test 与 release 模式都拒绝 usesCleartextTraffic=true。
完成代码评审并提交冻结后,从仓库根目录执行统一 RC 证据脚本。默认拒绝脏工作区;-AllowDirtyRehearsal -SkipBuild 只能用于验证脚本和 APK,生成的证据会明确标记为不可发布:
.\scripts\prepare-aug1-rc.ps1 `
-ApkPath '.\mobile-uni\dist\debug\bangdao-0.1.13-dcloud-test.apk' `
-BuildKind dcloud-test
脚本会复跑移动端测试/类型检查/H5/App 构建、管理端构建、后端定向测试和打包,验证 APK 后在被 Git 忽略的 output/aug1-rc/ 生成标准文件名、哈希及 JSON/Markdown 证据。它不执行生产同步、数据库迁移、服务重启或登录页人工同意操作。
2026-07-28 最终自定义基座大小为 21,158,193 字节,SHA-256 为 82D3352FF96A86F5DB4AC0C71DCB0ED6CEC98F2A785F6EAED2FE8D4FC0C5F704。2026-07-29 当前独立内测候选包为 bangdao-0.1.13-dcloud-test.apk:包名 com.yincheng.wygj、版本 0.1.13 (113)、targetSdkVersion=35,大小 33,921,543 字节,SHA-256 为 FA2D2A6DC84AE759714E6D16D146C1E1552A0F3F53C046069422012361D1D0C0,签名证书 SHA-256 为 AB06ECC0DE544DE73C385F3F0690B22966EBC12887FB8BEE1830CDBEFDEBEF5D。APK 反编译门禁确认包内业务资源等于当前 App-Plus 编译产物、启动原生隐私提示已关闭、登录页法务链接与未勾选拦截及身份加载失败关闭已进入包体,并通过敏感值、usesCleartextTraffic=false、networkSecurityConfig 和系统证书信任检查。干净提交 af8af2f6dd169e4616a4ca0ca724e8b809502ab3 的统一 RC 已完成,releaseEligible=true,证据在 output/aug1-rc/0.1.13-113-af8af2f6-frozen/;候选后端 JAR SHA-256 为 93AD272118F6A28F88C2BFA305F5C450E163CBE22577FF5BE3E85B3BD3958DAD。双提交交付包为 output/aug1-release/bangdao-aug1-0.1.13-113-af8af2f6-opscc1865a9.zip,大小 192,927,433 字节、SHA-256 为 CEF051549940B2605B3515137338EE4BB82719E04B03458EB523C71589B7309C,14 个条目和内部哈希已复核;0.1.12 及更早 RC/交付 ZIP 只保留为历史基线。当前 AVD 为 x86_64,APK 原生库仅含 arm64-v8a/armeabi-v7a;安装和原生外壳可由系统转译运行,但 DCloud Weex JS 进程实际出现 spinWaitPeer/IPC 超时,页面主体空白不能用于判断产品页面。浏览器验证只作补充,不替代 App 运行;不会为了模拟器改变正式 ABI、回退为 H5 壳或增加业务兜底。该包仍使用 DCloud 云端测试证书,只能作为 8 月 1 日受控内测包;企业正式 release 还必须使用签认后的企业证书摘要。
企业正式签名 APK 还必须用发布负责人保管的证书摘要执行 release 模式核验;该模式会额外拒绝 debuggable=true、明文 HTTP 和签名摘要不一致:
& '.\mobile-uni\scripts\verify-android-apk.ps1' `
-ApkPath '<企业签名 RC APK 绝对路径>' `
-BuildKind release `
-ExpectedSignerSha256 '<已签认的企业证书 SHA-256>'
发布前尚需提供的资产
- 当前受控内测版《服务协议》《隐私政策》已部署到
https://peilian.njzhmj.top/legal/,服务器发布前备份为/opt/wygj/backups/www-20260728224710;仍需公司法务对正文、处理者信息、第三方清单和保存期限正式签认。Android 登录页已使用实际链接且启动不再弹出原生确认;iOS 仍需在后续出包时复核相应的麦克风、相机、相册/文件用途说明。 - 无透明通道的 1024×1024 App Store 图标,以及 Android 自适应图标/启动图。
- 企业持有的 Android 签名证书、Apple Team、Bundle ID 注册与 iOS 发布证书。上述资产缺失时可以完成代码与真机调试,不能声称已具备商店上架条件。
已接入的资产与隐私模板
- 图标和启动图由
scripts/generate-app-assets.sh从现有src/static/brand-logo.png生成,输出位于src/static/app/,并由manifest.json显式关联。iOS App Store 图标为 1024×1024、无 alpha、未预制圆角;生成后可用npm --prefix mobile-uni run verify:app-assets校验尺寸和映射。 - 现有品牌源图仅为 64×64,因此这里生成的是可用于自定义基座和测试包的派生资产。正式提交商店前应替换为品牌方提供的高分辨率母版,再重新执行生成和预检。
androidPrivacy.json.example是原生提示策略模板,固定prompt=none;生成文件被 Git 忽略,模板和校验逻辑才是版本化事实源。两个公开法务 URL 的版本化事实源是mobile-uni/.env,configure:app-legal会校验它们,登录页和 APK 门禁必须使用同一组地址。- iOS 已按实际功能填写麦克风和照片库用途说明;不申请相机、定位、通讯录、蓝牙或广告追踪权限。
build:app依赖@dcloudio/uni-app-plus,它必须与@dcloudio/uni-app、@dcloudio/uni-h5、@dcloudio/vite-plugin-uni同版本。缺少 App 编译器时命令不报错,只静默产出带/h5/基路径的 H5 空壳,产物里没有app-service.js与app-renderjs.js,App 平台代码等于从未编译。判定build:app是否真的成功要看产物中是否存在app-service.js、app-renderjs.js、manifest.json,不能只看DONE Build complete.。- App-Plus 实时对练通过
renderjs在系统 WebView 中执行媒体/WebRTC;认证 SDP 与工具请求仍由逻辑层代理。发布前必须在 Android/iOS 真机验证麦克风授权、实时转写、远端语音播放、前后台切换和断线降级。 - 真机步骤和证据口径见
docs/MOBILE_APP_DEVICE_ACCEPTANCE.md。资源预检通过不等于 Android/iOS 真机或应用商店验收通过。
调试基座版本不匹配
若真机提示“本应用使用 HBuilderX X 或对应 CLI 版本编译,而手机端 SDK 版本是 Y”,先核对编译依赖与基座,不要修改 Android minSdkVersion:
node -e "for (const n of ['@dcloudio/uni-app','@dcloudio/uni-app-plus','@dcloudio/uni-h5','@dcloudio/vite-plugin-uni']) console.log(n, require('./mobile-uni/node_modules/'+n+'/package.json').version)"
Windows PowerShell 再核对 HBuilderX CLI 与设备;项目已导入 HBuilderX 且设备在线后,才执行最后一条运行命令:
& 'D:\HBuilderX\cli.exe' version
& 'D:\HBuilderX\cli.exe' devices list --platform android
& 'D:\HBuilderX\cli.exe' launch app-android `
--project (Resolve-Path '.\mobile-uni').Path --deviceId <adb-serial> `
--playground standard --native-log true
标准基座可先验证编译器/SDK 兼容、启动和页面交互;完整权限验收必须先生成 5.22 自定义基座,再把上面的 standard 改为 custom 重跑。不要在真机运行命令中加 --compile true,该参数表示“只编译代码”,不会安装或启动手机端应用。
当前项目依赖已与 HBuilderX 5.22 统一;升级后必须重新生成并安装 5.22 自定义运行基座,旧的 5.15 基座不能继续用于真机验收。命令行资源构建通过只证明编译链可用,不等同于已完成真机基座验证。
更新策略
涉及原生权限、插件、证书或 App 壳的改动必须重新云打包并通过应用商店/TestFlight 发布。仅 JavaScript/CSS/静态资源的热更新(WGT)不作为首个试点版本的发布方式;如后续启用,须有版本兼容、完整性校验、灰度与回滚方案。