一、车载应用商店与分发:AAB格式打包、车载应用签名、OTA更新、渠道分发
说实话,车载应用分发这件事,跟手机端完全是两码事。我最早做车机互联的时候,天真地以为把APK扔到应用商店就完事了。结果呢?第一次OTA测试就把我折腾得够呛——签名不对、格式不兼容、渠道包乱飞……嗯,今天咱们就把这块硬骨头啃下来。
1.1 AAB格式打包:为什么Google非要推这个?
Android App Bundle(AAB)是Google官方推荐的发布格式。说白了,它不是一个安装包,而是一个“安装包生成器”。你上传AAB到商店,商店根据用户设备的屏幕密度、CPU架构、语言等,动态生成最合适的APK。
我在项目中遇到过一个问题:车载设备的屏幕密度五花八门,有的车机是mdpi,有的直接上xxxhdpi。如果用传统APK,你得把所有资源都塞进去,包体动不动就200MB+。换成AAB后,用户下载的APK只有60MB左右,体验好太多了。
- 按需分发:只下载当前设备需要的资源
- 减小包体:平均减少30%-50%的安装包大小
- 动态功能模块:支持按条件加载功能(比如仅在中国区加载高德地图模块)
怎么打包?Android Studio里直接选Build > Build Bundle(s) / APK(s) > Build Bundle(s)。但注意,AAB不能直接安装到设备上,你得用bundletool转换成APK才能测试。
// 安装bundletool
brew install bundletool
// 将AAB转换为APK并安装到设备
bundletool build-apks --bundle=app.aab --output=app.apks --ks=keystore.jks --ks-pass=pass:123456
bundletool install-apks --apks=app.apks
你想想看,如果每次测试都要走一遍这个流程,是不是很烦?所以我建议在CI/CD里集成这个步骤,让机器去干这些重复劳动。
1.2 车载应用签名:别让签名成为你的噩梦
签名这件事,看似简单,但坑特别多。我记得有一次,客户反馈说“应用安装失败”,查了半天,结果是签名证书过期了。嗯,车载设备的生命周期通常很长(5-10年),所以签名的有效期一定要设置得足够长。
Android支持两种签名方案:v1(JAR签名)和v2(APK签名方案)。从Android 7.0开始,v2是强制要求。但车载设备有些是Android 6.0的老系统,所以你得同时支持v1和v2。
- 签名证书的有效期建议设为25年(别问我为什么是25年,行业惯例)
- 使用相同的签名证书进行所有更新,否则用户无法覆盖安装
- 如果使用AAB,必须使用v2签名
// 生成签名证书(有效期25年)
keytool -genkey -v -keystore car_keystore.jks -keyalg RSA -keysize 2048 -validity 9125 -alias car_app
// 查看签名信息
keytool -list -v -keystore car_keystore.jks
我曾经犯过一个低级错误:把debug签名当release签名用了。结果应用商店审核不通过,还得重新打包。所以,我建议你在项目的gradle.properties里配置好签名信息,避免手误。
1.3 OTA更新:让用户无感升级
OTA(Over-The-Air)更新是车载应用的核心能力。你想想看,用户不可能像手机一样天天去应用商店检查更新。所以,自动静默更新是刚需。
Android Automotive的OTA更新机制,说白了就是系统级应用商店。它支持两种模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 静默更新 | 后台下载,安装时提示用户重启 | 系统应用、安全补丁 |
| 用户触发 | 用户手动点击“检查更新” | 第三方应用 |
我在项目中实现过一个OTA更新模块,核心逻辑是这样的:
- 应用启动时,向更新服务器请求最新版本号
- 如果版本号大于当前版本,下载AAB文件
- 下载完成后,调用PackageInstaller进行静默安装
- 安装成功后,重启应用或提示用户重启
// 检查更新
fun checkUpdate(context: Context, currentVersion: Int) {
val latestVersion = getLatestVersionFromServer()
if (latestVersion > currentVersion) {
downloadAndInstall(context, latestVersion)
}
}
// 静默安装
fun installApk(context: Context, apkFile: File) {
val packageInstaller = context.packageManager.packageInstaller
val sessionParams = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = packageInstaller.createSession(sessionParams)
val session = packageInstaller.openSession(sessionId)
// 写入APK数据
session.openWrite("package", 0, apkFile.length()).use { out ->
apkFile.inputStream().use { input ->
input.copyTo(out)
}
}
session.commit(IntentSender(...))
}
1.4 渠道分发:不同车厂,不同玩法
车载应用的分发渠道,比手机复杂得多。每个车厂都有自己的应用商店,而且审核标准、签名要求、API限制都不一样。
我整理了一下常见的渠道分发方式:
- 车厂自有商店:比如比亚迪的DiLink商店、蔚来的NIO Life。需要对接车厂的SDK,上传AAB包。
- 第三方商店:比如华为应用市场(车载版)、腾讯应用宝(车载版)。这些商店通常有统一的接入标准。
- 预装合作:直接跟车厂合作,把应用预装到车机里。这种方式最稳定,但商务谈判周期长。
- OTA推送:通过车厂的OTA系统,直接推送到用户车机上。适合系统级应用。
我记得有一次,我们同时对接了三个车厂的商店,每个商店的签名要求都不一样。有的要求使用车厂提供的签名证书,有的允许使用自己的证书。最后我们搞了一个“渠道打包工具”,根据不同的渠道自动配置签名和元数据。
- 使用Gradle的productFlavors来管理不同渠道
- 每个渠道配置独立的applicationId和签名证书
- 在AndroidManifest中通过占位符注入渠道信息
// build.gradle 渠道配置
android {
productFlavors {
byd {
applicationId "com.example.app.byd"
versionName "1.0.0-byd"
manifestPlaceholders = [CHANNEL: "byd"]
}
nio {
applicationId "com.example.app.nio"
versionName "1.0.0-nio"
manifestPlaceholders = [CHANNEL: "nio"]
}
}
}
你想想看,如果每个渠道都手动打包,那得累死。所以,自动化是必须的。我建议在CI/CD里配置多个构建任务,每个任务对应一个渠道,自动签名、自动上传。
知识体系总览
下面这张图,是我根据多年经验总结的车载应用分发全流程。你可以把它当作一个检查清单,做项目时对照着来。
嗯,以上就是车载应用商店与分发的核心内容。从AAB打包到签名,从OTA更新到渠道分发,每一步都有它的门道。我个人觉得,最关键的还是自动化——把重复劳动交给机器,把精力留给真正需要思考的问题。