Unity Android 混淆踩坑:升级 AGP 后找不到 Java 方法
打新版本 APK 时,我遇到了一个问题:应用启动后黑屏,日志提示 Unity 找不到对应的 Java 方法。这个版本的 C# 和 Java 代码都没有修改,构建配置却有一处变化:Android Gradle Plugin(AGP)从 8.2.2 升级到了 8.6.0。
排查后,我把问题定位到了 AGP 8.4 开始引入的库模块缩减行为变化。本文记录这个变化如何影响 Unity 导出工程,以及混淆规则应该放在哪里。
为什么没改代码,方法却找不到了?
这里升级的是 AGP 插件版本,要和 gradle-wrapper.properties 中的 Gradle 版本区分开。两者有关联,但不是同一个版本号。
AGP 8.4 发布说明提到:如果 Android 库子项目开启了代码缩减,提供给依赖它的应用模块的将是缩减后的类。
放到 Unity 导出工程中,可以这样理解:launcher 是应用模块,依赖 unityLibrary 库模块。如果 unityLibrary 开启了 minifyEnabled,它的代码就可能先被处理,再交给 launcher 打包。不能再依赖旧版本中应用模块拿到未缩减库代码的行为。
而我配置的混淆规则中,没有明确类名,而是使用* implements 进行匹配。因为 AGP 规则的修改,就导致我的规则不再生效了。
调整两个模块的混淆配置
对于这个 Unity 导出工程,我采用的方案是:关闭 unityLibrary 自身的缩减,由 launcher 在最终构建时统一处理,并让库模块提供需要保留的接口规则。
下面使用 Groovy DSL,展示需要合并到现有 build.gradle 中的配置。保留工程已有的 Unity、SDK 规则和其他构建设置,不要直接覆盖整个文件。
1. unityLibrary 提供保留规则
在 unityLibrary/build.gradle 中配置:
android { |
2. launcher 开启最终混淆
在 launcher/build.gradle 中配置:
android { |
两个配置项的区别是:
| 配置项 | 作用 |
|---|---|
proguardFiles |
当前模块执行缩减时使用的规则 |
consumerProguardFiles |
库提供给使用方、在应用构建阶段生效的规则 |
为 Unity 调用的 Java 方法编写保留规则
假设自定义 Activity 的完整类名是 com.example.game.GameActivity,其中定义了一个供 Unity 调用的实例方法:
public class GameActivity extends com.unity3d.player.UnityPlayerActivity { |
那么,在 unityLibrary/proguard-rules.pro 中添加:
-keep class com.example.game.GameActivity { |
这是保留规则,不是 Java 类定义:需要写 -keep,方法声明以分号结束,不写方法体。这个示例保留目标类和指定方法,不会把该类的所有成员都列入保留范围。
使用时,把示例类名替换为工程中实际声明该方法的类名,并核对返回值、参数类型及是否为 static。例如实际签名是 SetPlatformId(int),就应写成:
-keep class com.example.game.GameActivity { |
用 Release 包验证
修改配置后,重新构建开启混淆的 Release 包进行测试。
这次排查给我的提醒是:跨语言调用不仅要关注保留了哪些接口,还要确认这些规则在哪个构建阶段生效。
升级构建工具后,即使业务代码没变,也需要重新验证开启混淆的正式包。



