跳转至

Android(安卓)上架流程与构建文档

点击下载 h5_iOS_Android.zip

目录


第一部分 上架完整流程

1. 流程总览

准备资质材料
   └─ 营业执照 / 身份证、软件著作权、隐私政策、App 备案
        ↓
注册开发者账号(Google Play / 华为 / 小米 / OPPO / vivo / 应用宝 / 荣耀)
        ↓
开发者实名认证(个人)或企业认证(对公打款 / 授权函)
        ↓
生成签名密钥库 release.jks(keytool 或 Android Studio)
        ↓
把签名配置写进 android/app/build.gradle
        ↓
构建 H5 产物 → 同步到 Android → 打签名包(AAB 上架 / APK 测试)
        ↓
商店后台创建应用 → 填写商店信息 → 上传包 → 上传资质
        ↓
提交审核 → 通过 → 发布上架

一次完整的首次上架,卡点通常不在打包,而在「实名/企业认证」和「资质材料」这两步,需要预留时间。按华为《实名认证》文档:企业打款认证最快 30 分钟人工审核 1~2 个工作日;个人人脸识别或个人银行卡认证即时完成、人工审核 1~2 个工作日。各平台官方文档都没给出商店审核时长的承诺值,按实际排队情况预留。

2. 上架前需要准备的材料

材料 用途 说明
营业执照(企业)或身份证(个人) 开发者账号实名/企业认证 企业还需法人身份证、对公银行账户
对公银行账户 企业认证打款验证 部分平台以打款小额随机金额方式验证
开发者资质授权函 企业认证 平台提供模板,需盖章
软件著作权登记证书 或 软件版权声明 上架资质 华为官方原文口径为软著属「非必选资质」,但建议申请《计算机软件著作权登记证书》《APP电子版权证书》或《软件著作权认证证书》以保护知识产权;游戏品类必需(软著 + 版号)。证书上的软件名称须与上架应用名称一致,著作权人须与开发者名称一致。软著登记周期较长,建议提前办
App 备案号(工信部) 国内商店上架 备案不在应用商店做,在云服务商(接入商)的备案系统做 —— 华为云/阿里云/腾讯云/移动云/天翼云/联通云。存在多个包名时所有包名均需备案;备案的包名、应用名称、主体信息必须与在架信息一致。无需备案的两类:单机应用(未通过公共互联网提供互联网信息服务)、境外应用(境外主体运营且服务器仅置于境外)。未备案会导致商店搜索与展示受限、安装时提示「应用未核准(备案)」
ICP 备案 / 域名备案 应用内访问的服务端域名 服务端域名需已备案
隐私政策页面(可公网访问的 URL) 商店信息填写 + 审核 需说明收集的个人信息、用途、第三方 SDK 清单
应用图标、应用截图、应用介绍 商店详情页 图标与截图尺寸各平台不同,按后台提示准备
测试账号 提交审核 需要登录才能用的 App 必须提供可用测试账号,否则会因「无法测试」被驳回
签名密钥库 release.jks 打包签名 见第 4 节

如果丢进 dist/ 的 Web 产物需要登录才能进主界面,提交审核时必须一并提供可用测试账号和服务器地址,否则审核方进不去,会按「无法测试」驳回。

3. 注册开发者账号

3.1 Google Play(海外分发)

  1. 准备一个 Google 账号(建议用公司邮箱,不要用个人私有账号)。
  2. 打开 Google Play Console 注册页:https://play.google.com/console/signup
  3. 选择账号类型:
  4. 个人账号(Personal):认证材料相对简单;
  5. 组织账号(Organization):需要 D-U-N-S 编号(邓白氏编码;Apple 官方口径为「大多数司法管辖区免费申请」,申请周期通常 5~30 个工作日),用公司名称作为发布者名称必须走这条路。
  6. 缴纳注册费:一次性 25 美元,需国际信用卡。金额以 Play 管理中心注册页当时显示的为准。
  7. 完成身份验证:上传身份证明、地址证明;组织账号还需验证组织信息与法人。
  8. 填写开发者资料:开发者名称(展示给用户)、联系邮箱、联系电话、网站。
  9. 认证通过后即可创建应用。

Google Play 的签名机制(重点):Google Play 默认启用 Play App Signing(Play 应用签名)。这时存在两把 key: - 上传密钥(upload key):就是你本地的 release.jks,用来给上传到 Play 的 AAB 签名; - 应用签名密钥(app signing key):由 Google 托管,最终分发给用户的 APK 用它签名。

好处是上传密钥丢了可以向 Google 申请重置;但应用签名密钥一旦确定不可更换

3.2 华为应用市场(AppGallery)

  1. 注册华为开发者账号:https://developer.huawei.com/consumer/cn/
  2. 实名认证:
  3. 按华为《实名认证》文档:企业三选一 —— ① 打款认证(官方推荐,最快 30 分钟):企业对公账号 + 法定代表人姓名 + 身份证号;② 人工审核(1~2 个工作日):营业执照原件扫描件或照片 + 法定代表人手持身份证正反面照片或人脸识别;③ 华为云授权认证(账号已在华为云实名为企业客户)。个人四选一 —— 人脸识别(推荐,即时完成)、个人银行卡(推荐,即时完成)、人工审核(1~2 个工作日)、华为云授权认证。
  4. 官方认证方式列表中不含任何收费项,此前"企业认证需支付认证费"的说法未在官方文档中出现,已删除。
  5. 企业认证暂不支持电子营业执照,须提供最新「三证合一」营业执照照片或扫描件,且信息与国家企业信用信息公示系统一致;法人为港澳台人士可提交手持通行证或护照照片,海外人士提供手持护照照片。不支持港澳台、海外企业及海外个人注册认证中国大陆开发者联盟账号(须走海外官网)。
  6. 进入 AGC(AppGallery Connect)https://developer.huawei.com/consumer/cn/service/josp/agc/index.html
  7. 创建应用。当前路径(AGC 帮助《创建应用》,更新于 2026-07-22):先在「证书、APP ID 和 Profile > APP ID」新建 APP ID(填应用类型、应用名称、应用包名、应用分类),再在 APP ID 列表中点「发布」为该 APP ID 关联创建待发布应用(填支持设备、默认语言),完成后才会出现在「APP 与元服务」列表中;旧版「我的应用 → 新建」已不是当前入口。仓库默认的 Android 包名是 com.d3.app

    包名与应用分类一旦创建均不可修改,务必先确认。包名命名规范(段数、字符、保留字)见鸿蒙文档第 5.1 节。

  8. 填写应用信息:图标、简介、详细介绍、截图、隐私政策 URL、版本说明、应用权限说明。
  9. 上传软著/著作权声明、App 备案号等资质。
  10. 上传签名包(华为 Android 应用一般收 APK)。
  11. 提交审核。

3.3 小米应用商店

  1. 注册小米开放平台账号:https://dev.mi.com/
  2. 完成开发者实名认证(个人/企业),企业需营业执照 + 对公账户。
  3. 「应用管理」→ 创建应用,填写包名、应用名。
  4. 上传 APK、应用图标、截图、简介、隐私政策链接、软著、备案号。
  5. 提交审核。

3.4 OPPO / vivo / 应用宝 / 荣耀

流程与小米高度一致:注册 → 实名/企业认证 → 创建应用 → 上传 APK 与资质 → 提交审核。入口:

商店 开放平台地址
OPPO 软件商店 https://open.oppomobile.com/
vivo 应用商店 https://dev.vivo.com.cn/
应用宝(腾讯) https://open.qq.com/
荣耀应用市场 https://developer.honor.com/

国内多渠道分发时,同一个 App 在所有渠道必须使用同一个签名密钥库,否则用户无法跨渠道覆盖安装升级。

4. 生成签名认证文件(密钥库 .jks)

Android 的「认证文件」就是一个 Java 密钥库(keystore),扩展名一般是 .jks.keystore,里面存放签名用的私钥和自签名证书。Android 不需要向平台申请证书(这一点和 iOS、鸿蒙不同),密钥库由开发者自己生成,平台只校验签名一致性。

4.1 方式一:Android Studio 图形界面生成

  1. 菜单 Build → Generate Signed App Bundle / APK

Generate Signed App Bundle or APK

  1. 首次没有密钥库时,点击 Create new... 新建。

首次需要先创建密钥库文件

  1. New Key Store 弹窗里填写各字段,字段含义见下图标注:

New Key Store 字段说明

4.2 方式二:keytool 命令行生成(推荐,可复现)

keytool 随 JDK 提供,确认 java/keytool 在 PATH 中即可:

keytool -genkeypair -v \
  -keystore release.jks \
  -storetype PKCS12 \
  -keyalg RSA -keysize 2048 \
  -validity 10950 \
  -alias release

执行后会依次询问密钥库口令、姓名(CN)、组织单位(OU)、组织(O)、城市(L)、省份(ST)、国家代码(C)。

  • -validity 10950 约 30 年。按 developer.android.google.cn 的应用签名文档:签名密钥的有效期必须在 2033 年 10 月 22 日以后结束,此项由 Google Play 强制执行,官方建议使用 25 年或以上的有效期,因此不要用默认的很短有效期。
  • 生成好的密钥库放在 h5_iOS_Android/android/app/release.jks、别名用 release,就能直接对应第 5 节的示例配置。

4.3 密钥库字段说明

字段 含义 建议
Key store path 密钥库文件保存路径 放到工程外的安全目录,不要提交到仓库
Password / Confirm(上半部分) 密钥库口令 用密码管理器保存
Alias 密钥别名 本文示例用 release
Password / Confirm(Key 部分) 密钥口令 可与密钥库口令不同
Validity (years) 证书有效年限 ≥ 25 年
First and Last Name (CN) 通用名 一般填应用名或负责人
Organizational Unit (OU) 部门 Mobile
Organization (O) 组织/公司全称 会写进证书,用户可见
City / State / Country Code 城市/省/国家码 国家码用两位,如 CN

4.4 提取公钥与证书指纹

第三方 SDK(地图、推送、登录等)常需要提供签名的 MD5/SHA1/SHA256 指纹:

# 方式一:直接列出密钥库中证书的全部指纹
keytool -list -v -keystore release.jks -alias release

# 方式二:先导出 PEM 公钥证书,再 dump 指纹(Windows 下常用)
keytool -exportcert -rfc -keystore release.jks -alias release > cert.pem
certutil -dump cert.pem
# 方式三:直接校验已打好的 APK 用的是哪把 key
<Android SDK>/build-tools/<版本>/apksigner verify --print-certs app-release.apk

4.5 保管要求

  • release.jks 和两个口令丢失即无法再更新已上架的应用(Google Play 走 Play App Signing 时可申请重置上传密钥,国内商店基本无解,只能改包名重新上架)。
  • 密钥库文件、口令不要进 Git 仓库,写进 .gitignore,通过密码管理器等受控渠道分发给需要的人。

5. 把签名配置接入工程

签名配置写在 h5_iOS_Android/android/app/build.gradle

android {
    signingConfigs {
        release {
            storeFile file("release.jks")
            storePassword "******"
            keyAlias "release"
            keyPassword "******"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

仓库里的写法android/app/build.gradle 没有用上面那种四个值明文硬编码的写法,而是从 android/keystore.properties 读取,即下面「推荐写法」那一段。仓库里只带 keystore.properties.example 模板,release.jkscert.pemkeystore.properties 都在 .gitignore 里,不随仓库分发。

所以拿到这份开源代码后,打 release 包前必须自己补两样东西,否则签名会失败:

  1. 把自己的密钥库放到 android/app/release.jks(或放别处,用下面的 storeFile 指向它);
  2. 复制 android/keystore.properties.exampleandroid/keystore.properties,填入真实的 storePassword / keyAlias / keyPassword

只出 debug 包(.\gradlew assembleDebug)不需要这两步,Gradle 会用默认调试签名。

推荐写法(对外开源版本):

// android/app/build.gradle
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    signingConfigs {
        release {
            storeFile file(keystoreProperties['storeFile'] ?: 'release.jks')
            storePassword keystoreProperties['storePassword'] ?: ''
            keyAlias keystoreProperties['keyAlias'] ?: ''
            keyPassword keystoreProperties['keyPassword'] ?: ''
        }
    }
}
# keystore.properties.example(提交到仓库,不含真实值)
storeFile=release.jks
storePassword=
keyAlias=release
keyPassword=

另外 android/local.properties 里记录的是本机 Android SDK 路径,属于本地环境文件,不应提交仓库

6. 产物格式选择:AAB 还是 APK

Build → Generate Signed App Bundle / APK 的第一步就是选格式:

选择 Android App Bundle 还是 APK

  • Android App Bundle(.aab):上架用。Google Play 对新应用要求以 AAB 上传,具体以 Play Console 帮助中心的当前说明为准。
  • APK:给真机装包测试、内部分发用。国内商店目前主要收 APK。

命令行对应关系:

# APK(release,已签名)
./gradlew assembleRelease      # Windows: .\gradlew assembleRelease

# AAB(release,已签名)
./gradlew bundleRelease        # Windows: .\gradlew bundleRelease

产物位置:

类型 路径
release APK android/app/build/outputs/apk/release/app-release.apk
release AAB android/app/build/outputs/bundle/release/app-release.aab
debug APK android/app/build/outputs/apk/debug/app-debug.apk

7. 商店后台创建应用并提交审核

以国内商店为例的通用步骤:

  1. 后台创建应用,填入包名(仓库默认 com.d3.app)与应用名(仓库默认 示例应用,定义在 capacitor.config.tsandroid/app/src/main/res/values/strings.xml)。
  2. 上传签名包。上传后后台会自动解析包名、版本号(versionCode / versionName,定义在 android/app/build.gradle)、目标 SDK。
  3. Google Play 的目标 API 级别要求developer.android.google.cn《满足 Google Play 的目标 API 级别要求》官方原文):自 2026 年 8 月 31 日起,新应用和应用更新必须以 Android 16(API 级别 36)或更高版本为目标平台,才能提交到 Google Play;Wear OS 与 Android Automotive OS 应用除外,须以 API 35 及以上为目标;Android TV 与 Android XR 应用也除外,须以 API 34 及以上为目标。现有应用若要对更高版本系统设备的新用户可用,targetSdk 须不低于 35。
  4. 仓库默认 compileSdk/targetSdk35minSdk23(见 android/variables.gradle),不满足上面这条要求,提交 Google Play 前必须把 targetSdk 升到 36。官方留有延期通道:可在 Play 管理中心的应用延期表单申请延期至 2026 年 11 月 1 日。唯一豁免是「仅限特定组织内部用户使用且仅供内部分发的永久专用应用」。
  5. 升级 targetSdk 属工程改动,本次未执行。
  6. 填写商店详情:图标、截图、一句话简介、详细介绍、更新说明、分类、关键词。
  7. 填写合规信息:隐私政策 URL、权限使用说明、个人信息收集清单、第三方 SDK 清单、是否含广告、年龄分级。
  8. 壳里已声明的权限见 android/app/src/main/AndroidManifest.xml,其中 MANAGE_EXTERNAL_STORAGE(访问公共目录)在各商店尤其是 Google Play 审核非常严格,如果业务不必须,建议上架前移除
  9. 上传资质:软著或电子版权证书(华为口径为非必选资质,游戏品类必需)、App 备案号、行业许可证(如需要)。华为侧上传入口为「AGC > APP与元服务 > 点击应用名称 > 版本信息 > 版权信息」;资质图片要求:原件拍照或彩色扫描件(或加盖公章的复印件)、在有效期内、不可隔屏拍摄、边角完整内容清晰(国徽不得遮挡)、无反光、水印只能一行且不遮挡重要信息,支持 JPG / PNG / BMP / PDF
  10. 提交审核 → 等待结果 → 通过后选择立即发布或定时发布。

8. 常见驳回原因

  • 未提供测试账号,或提供的账号无法登录(产物需要登录时必须提供);
  • 权限申请与功能不匹配,尤其是 MANAGE_EXTERNAL_STORAGECAMERA、定位类权限;
  • 隐私政策缺失、无法访问,或未列明第三方 SDK;
  • 缺少 App 备案号(国内强制,未备案会提示「应用未核准(备案)」并影响商店搜索与展示);软著在华为口径下属「非必选资质」,但部分商店与部分品类(尤其游戏)仍强制要求;
  • 应用内含"更新提示/自更新"能力被判定为绕过商店分发。壳里集成了 @capgo/capacitor-updater 热更新(只更新 H5 资源,不替换原生包),需在审核说明中解释清楚"仅更新 Web 资源、不下发可执行代码",Google Play 对此尤其敏感;
  • 明文 HTTP 请求。仓库的 capacitor.config.tsserver.androidScheme: "http"android.allowMixedContent: true,并配了 network_security_config,如被判定为不安全传输需给出说明或改为 HTTPS。

9. 上架后的版本更新

  1. 提升版本号:android/app/build.gradleversionCode(整数,每次必须递增)和 versionName(展示字符串)。
  2. 重新走第二部分的构建打包流程,必须用同一个 release.jks 签名
  3. 后台新建版本 → 上传新包 → 填写更新说明 → 提交审核。

第二部分 构建与打包操作文档

这一部分讲怎么把 Web 产物装进 Android 壳、以及怎么打出可安装/可上架的包。

10. 环境要求

  1. Node / NPM 版本 >= 20
  2. Java / JDK 21(Android 构建依赖)。⚠️ 不能用 JDK 17:Capacitor 7 的 node_modules/@capacitor/android/capacitor/build.gradlesourceCompatibility / targetCompatibility 写死成 JavaVersion.VERSION_21,JDK 17 会在 :capacitor-android:compileReleaseJavaWithJavac 直接失败。最省事的做法是用 Android Studio 自带的 JBR(<Android Studio 安装目录>\jbr,例如 JBR 21.0.10),详见第三部分第 2 条。
  3. Android SDK(建议通过 Android Studio 安装与管理)
  4. Capacitor CLI —— 已在 devDependencies 里,npm install 之后用 npx cap 调用即可,不需要全局安装

拉到项目后先安装依赖:

npm install

Capacitor 官方文档:https://capacitorjs.com/docs/plugins

工程结构

这是一个纯原生壳工程,只有壳和配置,没有前端框架、没有业务代码、没有构建工具链:

路径 说明
android/ Android 壳工程。Android Studio 打开的就是这个目录,不是仓库根目录
ios/ iOS 壳工程,见 iOS 文档
dist/ Web 产物投放目录。你自己项目打包出来的 index.html 和静态资源直接丢进来,一个单文件 html 也可以。目录内容不入库,仓库里只有 .gitkeep 占位
capacitor.config.ts Capacitor 配置,webDir 已经指向 dist,不需要改
resources/ logo.png / splash.png 两张源图,npm run assets 据此生成 Android 与 iOS 全套图标和启动图
package.json 只声明 Capacitor 自身和插件依赖,没有任何前端框架

Android 侧的原生代码在 android/app/src/main/java/com/d3/app/

  • MainActivity.java:继承 BridgeActivity,负责崩溃日志落盘(Download/d3/logs/)、存储权限检查、WebView 参数配置。没有覆盖 WebView 的加载路径,走 Capacitor 默认行为,即加载 android/app/src/main/assets/public/index.html
  • StoragePermissionPlugin.java:自定义插件,向 Web 侧暴露 Download/d3/{assets,upgrade,logs} 的读写能力,配合热更新使用。

壳里用到的 Capacitor 插件

下面这份清单与 package.jsonandroid/capacitor.settings.gradleios/App/Podfile 三处一致。

插件 作用
@capacitor/core Capacitor 核心库
@capacitor/cli 命令行工具(cap sync / cap copy / cap open
@capacitor/assets 图标 / 启动页资源生成
@capacitor/android Android 平台支持
@capacitor/ios iOS 平台支持
@capacitor/app 应用生命周期管理、硬件返回键
@capacitor/dialog 原生弹窗
@capacitor/filesystem 文件读写
@capacitor/haptics 震动
@capacitor/keyboard 键盘
@capacitor/share 分享
@capacitor/splash-screen 启动画面
@capacitor/status-bar 状态栏
@capgo/capacitor-updater 热更新,从指定地址拉 dist.zip 并切换版本。当前配置 autoUpdate: falsestatsUrl: '',默认不联网

增删插件之后必须重新跑 npx cap synccapacitor.settings.gradlePodfile 都是 cap sync 生成的,手改会被覆盖。

11. 开发工具

  1. Android Studio(包含 SDK Manager)
  2. Android SDK 版本根据需求选择,可以下载内置的也可以单独下载然后引入;
  3. SDK Manager 里安装 platform-tools、对应 API Levelbuild-tools

SDK Manager

  1. 真机(建议 Android 8+)

12. 构建步骤

12.1 首次拿到代码(只做一次)

npm install      # 装 node_modules
npx cap sync     # 同步插件配置,并生成 android/capacitor-cordova-android-plugins/

这两步都不能跳:

  • android/capacitor.settings.gradleios/App/Podfile 全部用 ../node_modules/@capacitor/* 相对路径引用插件源码,没有 node_modules 直接编译不过;
  • android/settings.gradle 硬 include 了 :capacitor-cordova-android-pluginsandroid/app/build.gradleimplementation project(':capacitor-cordova-android-plugins'),但这个目录是 cap sync 的生成物、已被 android/.gitignore 排除,仓库里没有。跳过 cap sync,Gradle 第一句就报项目不存在。

12.2 日常:换一次 Web 产物

# 1. 把你的产物(index.html + 静态资源)放进 h5_iOS_Android/dist
# 2. 拷进 Android 工程
npx cap copy android
# 3. 打开 Android Studio
npx cap open android

package.json 里已经配好等价的 npm scripts:

命令 等价于 什么时候用
npm run copy cap copy 日常只换了 dist 内容,比 sync 快
npm run sync cap sync 增删了插件、或改了 capacitor.config.ts
npm run open:android cap open android 打开 Android Studio
npm run assets capacitor-assets generate 换了 resources/ 里的图

dist/ 不是 Android 直接读取的目录。 Android 实际加载 android/app/src/main/assets/public/index.htmlcap copy 负责把 dist/ 整体拷过去(该目录同样被 .gitignore 排除)。只把文件丢进 dist/ 就去点 Build,打出来的还是上一次的内容。

从仓库拉下来的代码已带配置好的 android 目录,不要执行 npx cap add android,会重置 MainActivity.javaAndroidManifest.xmlres/ 下的启动图资源等已有改动。

12.3 需要自己确认的工程配置

下面这些是仓库里的默认值,换成自己应用的信息:

位置 仓库默认值
capacitor.config.ts appId com.d3.app
capacitor.config.ts appName / ios.scheme 示例应用
android/app/build.gradle namespace / applicationId com.d3.app
android/app/src/main/res/values/strings.xml app_name / package_name / custom_url_scheme / slogan
android/app/src/main/AndroidManifest.xml 申请了 16 项权限,含相机、精确定位、蓝牙、MANAGE_EXTERNAL_STORAGE,用不到的建议删,见第三部分第 8 条

13. 打包

图形界面方式

  1. 在 Android Studio 中选择 Build → Generate Signed Bundle / APK
  2. 选择 AAB(上架)或 APK(真机测试);
  3. 选择/创建密钥库并填入口令;
  4. 配置完成后点击 Next,选择 Build Variant = release,点击 Create 开始创建正式包:

选择 release 并创建

命令行方式

# 在 h5_iOS_Android/android 目录下执行
.\gradlew assembleRelease    # 出 APK
.\gradlew bundleRelease      # 出 AAB
.\gradlew assembleDebug      # 出调试包,用默认调试签名,不需要 keystore.properties

完整流程:

cd <仓库根>\h5_iOS_Android

# 首次还需要 npm install,见 12.1
npx cap copy android           # 把 dist/ 拷进 android/app/src/main/assets/public/

# 关键:JDK 必须是 21,用 17 编不过,见第三部分第 2 条
$env:JAVA_HOME = 'C:\Program Files\Android\Android Studio\jbr'

cd android
.\gradlew assembleRelease

产物位置:android/app/build/outputs/apk/release/(AAB 在 outputs/bundle/release/

一次完整构建的参考数据

参考值
构建耗时 约 2 分 25 秒(非首次,Gradle 依赖已缓存)
产物 android/app/build/outputs/apk/release/app-release.apk,7.66 MB(体积取决于你放进 dist 的内容,壳本身约 3 MB)
签名 apksigner 验出 Signer #1 为发布证书主体,签名有效

打完包建议校验一下用的是哪把 key,别拿调试签名去上架:

# 在 h5_iOS_Android\android 目录下执行;build-tools 版本按本机实际安装的改
& "$env:LOCALAPPDATA\Android\Sdk\build-tools\35.0.0\apksigner.bat" verify --print-certs `
  app\build\outputs\apk\release\app-release.apk

输出里 Signer #1 certificate DN 应该是自己密钥库里的主体,SHA-256 digest 可以跟商店后台登记的指纹对一下。如果输出的是 CN=Android Debug,说明签名配置没生效(多半是 keystore.properties 缺失或口令为空),别上传。

14. 真机调试

  1. 手机打开开发者选项与 USB 调试,用可传输数据的数据线连接电脑后,Android Studio 可以识别到设备:

配置好之后的真机显示位置

  1. 可使用 Chrome 访问 chrome://inspect 进行真机 WebView 调试。

15. 注意事项

  1. 可以安装 nvm 工具统一管理 node 版本,版本过高会导致报错。
  2. 注意环境变量的配置,确保项目能够正常运行。
  3. 应用图标和启动页:源图是 resources/logo.pngresources/splash.png,换图后执行 npm run assets 重新生成 Android 与 iOS 全套尺寸。该工具(https://github.com/ionic-team/capacitor-assets要求项目根目录存在 assetsresources 文件夹,文件名不能改
  4. 崩溃日志位置:优先写 /storage/emulated/0/Download/d3/logs/crash-YYYYMMDD-HHmmss.txt,没有存储权限时退到应用私有目录 files/crash_logs/。逻辑在 MainActivity.java 的崩溃处理里。
  5. 提取 jks 文件中的公钥和证书指纹:
    keytool -exportcert -rfc -keystore release.jks -alias release > cert.pem
    certutil -dump cert.pem
    
    注意导出的 cert.pemrelease.jks 都在 .gitignore 里,别提交。
  6. 滑动退出在 iOS 环境下不生效,Android 正常。

第三部分 常见坑

  1. 首次执行 .\gradlew 会下载 Gradle 全量包gradle-8.11.1-all.zip),首次构建耗时会明显更长,需保证网络可达 services.gradle.org,或提前配好镜像。
  2. JDK 必须是 21,用 17 编不过。报错停在 :capacitor-android:compileReleaseJavaWithJavac,原文:
错误: 无效的源发行版:21

根因在 Capacitor 自己的构建脚本 node_modules/@capacitor/android/capacitor/build.gradle,那里写死了 JavaVersion.VERSION_21,跟 android/app/build.gradle 无关,改工程侧配置没用。处理:换 JDK 21,用 Android Studio 自带的 JBR 最省事:

$env:JAVA_HOME = 'C:\Program Files\Android\Android Studio\jbr'   # Android Studio 自带的 JBR 就是 21

也可以在 android/gradle.properties 里写 org.gradle.java.home=<JDK21 路径>,但那行是本机路径、不该入库。另外 JAVA_HOME 与 PATH 上的 java 版本不一致时 Gradle 以 JAVA_HOME 为准,所以显式指定这一条最可靠。 3. 克隆后没跑 npm install + npx cap sync 就构建,必然失败。两个原因叠加:capacitor.settings.gradle 按相对路径找 node_modules 里的插件源码;settings.gradle include 的 :capacitor-cordova-android-pluginscap sync 生成物、不入库。见 12.1。 4. 只把产物丢进 dist/ 就打包,包里还是旧内容。Android 读的是 android/app/src/main/assets/public/,中间必须有 npx cap copy android。这一步很容易漏,症状是改完没反应、以为缓存问题。 5. 启动图不会自己消失capacitor.config.tsSplashScreen.launchAutoHidefalse,而 MainActivity.java 只做了 registerPlugin 和 WebView 配置,没有任何隐藏启动图的原生代码,也就是说必须由 Web 侧主动调一次 SplashScreen.hide()。你丢进 dist/ 的产物如果不调这个方法,可能一直停在启动图上。两个处理方向:产物里加上这句调用,或者把 launchAutoHide 改成 true 并靠 launchShowDuration 自动收起。 6. 产物不要依赖外部 CDN。曾经出现过启动图之后直接黑屏,根因是 Web 侧把框架标成 external、从一个不可达的 CDN 域名加载 ES module,手机 DNS 解析失败、模块图中断,页面只剩一个空的挂载节点。壳只负责加载本地文件,产物自带的外链失败它救不了。真机调试用 Chrome chrome://inspect 看 Console 能直接定位这类问题。 7. capacitor.config.tsSplashScreen.layoutName: "splash" 是失效配置android/app/src/main/res/layout/ 下只有 activity_main.xml,没有 splash.xml。实际生效的启动图来自 res/values/styles.xmlAppTheme.NoActionBarLaunchandroid:windowBackground@drawable/splash_with_text),走的是 Android 12+ SplashScreen API 的 postSplashScreenTheme 机制。要换启动图改这里,或者补一个 splash.xml 让配置生效。 8. AndroidManifest.xml 申请了 16 项权限,包括 CAMERAACCESS_FINE_LOCATIONBLUETOOTH_SCANMANAGE_EXTERNAL_STORAGEREAD_MEDIA_*,是原业务的需求。MainActivity.onCreate 里还带存储权限检查,装上打开可能先弹授权框。用不到的建议删干净:一是省掉无谓的授权弹窗,二是 MANAGE_EXTERNAL_STORAGE 属于敏感权限,Google Play 和国内商店都会要求书面说明用途,说不清会被驳回。 9. aapt2 报 Failed to stat file ... android.jar 的 WARN:构建期间会反复出现,但不影响结果(最终仍 BUILD SUCCESSFUL),可忽略。 10. versionCode 每次上传商店必须递增,否则拒收(提示 build already exists)。当前 android/app/build.gradle 里是 versionCode 1 / versionName "1.0"。 11. 签名配置从 android/keystore.properties 读取build.gradle 里没有明文口令。仓库里不含 release.jkscert.pemkeystore.properties,只有 keystore.properties.example 模板;缺文件时 assembleRelease 会因为 storePassword 为空而失败,按第 5 节补齐即可。注意 keystore.properties 里填的是明文口令,这个文件永远不要入库。 12. targetSdk 当前是 35(见 android/variables.gradle)。Google Play 从 2026-08-31 起要求新应用与更新以 API 36 为目标,上架 Google Play 前需要升级并回归测试。国内商店暂无此要求。

搜索