在启用了 R8 的模块中发现重复 class

Duplicate class found in modules with R8 enabled

我创建了两个 aar 库:com.example:test1:1.0.0 和 com.example:test2:1.0.0。我将这些库添加到我的主应用程序中,并在构建后 Android-Studio 抛出错误:

Duplicate class com.example.utils.a found in modules classes.jar (com.example:test1:1.0.0) and classes.jar (com.example:test2:1.0.0)

我发现发生此错误是因为两个库在同一包 (com.example.utils) 中都有 classes,并且在混淆后 R8 创建 classes (a.class) 具有相同的全名(我在 aar 的 classes.jar 中看到了这个)。如果我在我的库的属性中禁用 R8,这个错误就消失了。

'a' 不是库 class:混淆后所有库 classe 名称保持不变,a.class 由 R8 额外添加到包中。 我阅读了 R8 文档,但没有发现任何有关此问题的信息。 有什么方法可以解决这个问题而无需在我的一个库中对包进行 ranaming 吗?

创建两个库时,最好使用两个不同的命名空间,否则在 "accidentally" a class 时,即使不使用 R8 也有可能出现重复的 classes具有相同的名称被添加到两者。所以在你的情况下使用 com.example.test1com.example.test2.

根据您的用例,不将 R8 应用于库,而是仅将 R8 应用于包括这两个库的最终应用程序可能也是更好的选择。缩小库主要是为了使分发大小更小,并重命名内部结构以避免库用户(无意或有意)依赖可能在库版本之间发生变化的内部结构。

缩减库时,您还需要考虑选项 -keeppackagenames 以确保所有重命名的 classes 都保留在库的包中。否则你可能会得到 class 例如a.a.a.a.class 在多个库中。

如果您无法控制的库出现此问题,可以使用 shadow 等工具进行重新定位。

您应该始终在 Java 或其他 JVM 语言的所有代码前加上 unique 包,以创建一个独特的 fully qualified name because any two classes with the exact same fully qualified name will cause a build error. This happens because the JVM only uses the fully qualified name string, saved initially in a single table, to instantiate all the classes and interfaces in the system. If the table will have more than one entry for a class/interface, it won't know which one to choose. You can read more about it here.

正如我在回答 中所描述的,混淆相关冲突的最佳解决方案是在每个库的 proguard-rules 文件中使用 -repackageclasses com.example:test#.ofs,同时替换 #分别使用 12。这会将所有混淆的 类 移动到 com.example:test#.ofs 包中,而所有未混淆的 类 将保留在它们的原始包中,并且保证不会发生冲突。

正如 Proguard documentation 所述:

-repackageclasses [package_name]

Specifies to repackage all class files that are renamed, by moving them into the single given package.