Cocos Creator Android打包与AAB发布踩坑记录

Cocos Creator Android打包与AAB发布踩坑记录

Google Play现在强制要求AAB格式,前段时间折腾Cocos Creator的Android打包踩了不少坑,记录一下。

AAB和APK的区别

Google Play从2021年开始推AAB,简单说就是按需下载:

特性 AAB APK
文件大小 更小 固定
动态分发 支持 不支持
Google Play 强制 已废弃

开发者上传AAB,Google Play会自动按设备配置(CPU架构、语言、屏幕密度)生成对应的APK给用户下载。

环境配置

签名配置

先搞个签名文件:

1
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

然后在build.gradle里配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
android {
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "your-password"
keyAlias "my-alias"
keyPassword "your-password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}

bundletool工具

本地测试AAB需要这个工具,去GitHub下载:
https://github.com/google/bundletool/releases

AAB打包流程

Cocos Creator构建配置

构建面板选择Android,注意这几项:

  • 包名:com.yourcompany.game(唯一)
  • API Level:33+(Android 13+)
  • 目标平台:选Android Studio(导出项目)
  • 资源压缩:开启

MultiDex问题

方法数超过65536就得开MultiDex,不然构建失败。

app/build.gradle

1
2
3
4
5
6
7
8
9
android {
defaultConfig {
multiDexEnabled true
}
}

dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
}

还得自定义Application:

1
2
3
4
5
6
7
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context context) {
super.attachBaseContext(context);
MultiDex.install(this);
}
}

然后在AndroidManifest.xml里声明:

1
2
<application android:name=".MyApplication" ... >
</application>

R8混淆错误

遇到Missing classes detected while running R8

  1. 找到app/build/outputs/mapping/release/missing_rules.txt
  2. 把内容复制到proguard-rules.pro
1
2
-dontwarn com.xxx.**
-keep class com.xxx.** { *; }

Play Asset Delivery资源分发

Google Play要求基础APK不超过150MB,游戏资源通常超了,得用PAD。

PAD工作原理

1
AAB文件 = Base APK(<150MB) + Asset Packs(游戏资源)

Base包含应用代码和启动必需配置,Asset Packs放美术、音频、关卡数据。

配置方法

创建Asset Pack模块,把资源放src/main/assets

build.gradle

1
2
3
4
5
6
7
8
apply plugin: 'com.android.asset-pack'

assetPack {
packName = "assetsPackGameRes"
dynamicDelivery {
deliveryType = "install-time" // 安装时分发
}
}

deliveryType有三种模式:

  • install-time:安装时自动下载(启动必需)
  • fast-follow:安装后自动下载
  • on-demand:按需下载(玩家点了再下)

app模块里声明:

1
2
3
4
5
android {
defaultConfig {
assetPacks = [':assetsPackGameRes']
}
}

Unity/Cocos特别注意

配置文件必须放app目录,不能放资源包:

1
2
3
app目录必须包含:
├── assets/bin/
└── assets/config/

我第一次弄的时候配置文件放错了位置,结果启动黑屏,折腾了半天才发现。

AAB转APK本地测试

生成APKS

1
2
3
4
5
6
7
java -jar bundletool-all-1.10.0.jar build-apks \
--bundle=app.aab \
--output=app.apks \
--ks=my-release-key.jks \
--ks-pass=pass:your-password \
--ks-key-alias=my-alias \
--key-pass=pass:your-password

安装到手机

1
java -jar bundletool-all-1.10.0.jar install-apks --apks=app.apks

验证资源结构

1
unzip app.aab -d aab_extracted/

检查:

  • Base目录<150MB
  • 资源包分离正确
  • 配置文件在正确位置

常见错误与解决

classes.dex冲突

1
Entry name 'classes.dex' collided

解决:

1
2
3
4
5
android {
packagingOptions {
exclude 'classes.dex'
}
}

ZipException bad signature

1
java.util.zip.ZipException: invalid LOC header

解决:删除损坏的jar包重新构建,或者清空gradle缓存。

Firebase连接错误

1
Connect to firebasecrashlyticssymbols.googleapis.com failed

国内网络环境常见问题,配置代理或者离线构建:

1
2
systemProp.http.proxyHost=proxy.company.com
systemProp.http.proxyPort=8080

NDK配置错误

1
NDK did not have a source.properties file

local.properties指定NDK路径:

1
ndk.dir=C:\\Users\\username\\AppData\\Local\\Android\\Sdk\\ndk\\25.1.8937393

Gradle缓存锁定

1
Could not read cache value from registry.bin

解决:

1
2
del C:\Users\username\.gradle\daemon\4.1\registry.bin.lock
gradle clean

URI权限错误

1
java.lang.SecurityException: UID does not have permission to content://...

解决代码:

1
2
3
4
5
6
7
8
9
public static void grantUriPermission(Intent intent, Uri uri, int permissionFlags) {
List<ResolveInfo> activities = appActivity.getPackageManager()
.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);

for (ResolveInfo info : activities) {
String packageName = info.activityInfo.packageName;
appActivity.grantUriPermission(packageName, uri, permissionFlags);
}
}

Android Studio代理配置

国内开发环境基本都需要配代理。

HTTP代理

File → Settings → Appearance & Behavior → System Settings → HTTP Proxy

Gradle代理

gradle.properties

1
2
3
4
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.https.proxyHost=www.somehost.org
systemProp.https.proxyPort=8080

Google Play上架

检查清单

  • AAB基础部分<150MB
  • 签名配置正确
  • 版本号递增
  • 隐私政策链接
  • 应用截图和描述

版本号管理

build.gradle

1
2
3
4
5
6
android {
defaultConfig {
versionCode 10001 // 必须递增
versionName "1.0.1"
}
}

上传流程

  1. Google Play Console登录
  2. 选择应用 → 发布 → 正式版
  3. 上传AAB文件
  4. 填写发布信息
  5. 提交审核(1-7天)

性能优化

资源优化

优化项 方法 效果
纹理压缩 ETC/ASTC格式 减少50%+
音频压缩 OGG格式 减少60%+
资源分离 PAD 基础包<150MB

启动屏优化

Cocos Creator默认启动屏不太好看,可以自己实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class AppActivity extends Cocos2dxActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startSplash();
}

private void startSplash() {
LinearLayout splash = new LinearLayout(this);
splash.setBackgroundColor(Color.BLACK);
splash.setLayoutParams(new LinearLayout.LayoutParams(-1, -1));
mFrameLayout.addView(splash);

// 延迟显示Logo
new Handler().postDelayed(() -> {
LinearLayout logoLayout = new LinearLayout(this);
logoLayout.setBackgroundColor(Color.WHITE);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);
logoLayout.addView(iv);
splash.addView(logoLayout);

AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
fadeIn.setDuration(1000);
logoLayout.startAnimation(fadeIn);
}, 500);

// 2.5秒后移除
new Handler().postDelayed(() -> {
mFrameLayout.removeView(splash);
}, 2500);
}
}

AndroidManifest.xml:

1
2
<activity android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" ... >
</activity>

AAB打包整体流程比APK复杂不少,特别是Play Asset Delivery的配置容易出错。关键点是:

  1. 基础包必须<150MB
  2. 配置文件位置不能错
  3. 国内网络记得配代理
  4. 版本号记得递增

有问题的欢迎留言讨论。