Unity Android 混淆踩坑:升级 AGP 后找不到 Java 方法

Unity Android 混淆踩坑:升级 AGP 后找不到 Java 方法

💡 原文中文,约2000字,阅读约需5分钟。
📝

内容提要

AGP 从 8.2.2 升级到 8.6.0 后,Unity 应用启动黑屏,日志提示找不到 Java 方法。原因是 AGP 8.4 起,若 unityLibrary 库模块开启代码缩减,会先输出缩减后的类,导致 launcher 中基于 * implements 的混淆规则失效。解决方案:关闭 unityLibrary 自身缩减,由 launcher 统一混淆,库模块通过 consumerProguardFiles 提供保留规则,并用 -keep 明确保留 Unity 调用的方法。

🔎

延伸解读

AGP 版本与 Gradle 版本的区别

文章特别提醒,AGP 插件版本与 gradle-wrapper.properties 中的 Gradle 版本是两回事,两者有关联但版本号不同。升级 AGP 时,不要误以为 Gradle 版本也同步升级,排查构建问题时应分别确认这两个版本,避免混淆问题根源。

库模块缩减行为变化的影响

AGP 8.4 起,若 Android 库子项目开启代码缩减,提供给应用模块的将是缩减后的类。在 Unity 导出工程中,若 unityLibrary 开启 minifyEnabled,其代码可能先被处理再交给 launcher 打包,导致 launcher 中基于 * implements 的混淆规则失效,进而出现找不到 Java 方法的问题。

混淆规则应放在哪个构建阶段

文章强调,跨语言调用不仅要关注保留了哪些接口,还要确认规则在哪个构建阶段生效。proguardFiles 用于当前模块执行缩减时的规则,consumerProguardFiles 则是库提供给使用方、在应用构建阶段生效的规则。关闭 unityLibrary 自身缩减、由 launcher 统一混淆,并让库模块通过 consumerProguardFiles 提供保留规则,是解决该问题的关键。

为 Unity 调用的方法编写精确保留规则

保留规则不是 Java 类定义,需要写 -keep,方法声明以分号结束,不写方法体。示例中只保留目标类和指定方法,不会保留该类的所有成员。使用时需替换为实际类名,并核对返回值、参数类型及是否为 static,例如 SetPlatformId(int) 应写成 -keep class com.example.game.GameActivity { public void SetPlatformId(int); }。

Q&A

为什么升级 AGP 后 Unity 应用启动黑屏,日志提示找不到 Java 方法?

因为 AGP 从 8.4 开始,如果 unityLibrary 库模块开启了代码缩减(minifyEnabled),它会先输出缩减后的类,导致 launcher 中基于 * implements 的混淆规则失效,从而 Unity 找不到对应的 Java 方法。

AGP 8.4 对库模块的代码缩减做了什么改变?

AGP 8.4 发布说明提到:如果 Android 库子项目开启了代码缩减,提供给依赖它的应用模块的将是缩减后的类。这意味着应用模块不能再依赖旧版本中拿到未缩减库代码的行为。

如何调整 unityLibrary 和 launcher 的混淆配置来解决这个问题?

关闭 unityLibrary 自身的缩减,由 launcher 在最终构建时统一处理,并让库模块提供需要保留的接口规则。具体配置:在 unityLibrary/build.gradle 中设置 minifyEnabled false 并配置 consumerProguardFiles;在 launcher/build.gradle 中设置 minifyEnabled true 并配置 proguardFiles。

proguardFiles 和 consumerProguardFiles 有什么区别?

proguardFiles 是当前模块执行缩减时使用的规则;consumerProguardFiles 是库提供给使用方、在应用构建阶段生效的规则。

如何为 Unity 调用的 Java 方法编写保留规则?

在 unityLibrary/proguard-rules.pro 中添加 -keep 规则,例如:-keep class com.example.game.GameActivity { public void SetPlatformId(); }。需要写 -keep,方法声明以分号结束,不写方法体。使用时替换为实际类名和方法签名。

修改混淆配置后如何验证?

重新构建开启混淆的 Release 包进行测试。升级构建工具后,即使业务代码没变,也需要重新验证开启混淆的正式包。

🏷️

标签

➡️

继续阅读