6

我创建了两个 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)中都有类,并且在混淆后,R8 创建了具有相同全名的类(a.class)(我在 aar 的 classes.jar 中看到了这个)。如果我在我的库的属性中禁用 R8,这个错误就消失了。

'a' 不是库类:经过混淆处理后,所有库类名称保持不变,并且 a.class 由 R8 额外添加到包中。我阅读了 R8 文档并没有发现任何关于这个问题的信息。有什么方法可以解决这个问题,而无需在我的一个库中重新命名包?

4

2 回答 2

5

创建两个库时,最好使用两个不同的命名空间,否则即使不使用 R8,当“意外”将同名的类添加到两者时,也可能会出现重复的类。所以在你的情况下使用com.example.test1and com.example.test2

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

在缩小库时,您还需要考虑-keeppackagenames确保所有重命名的类都保留在库的包中的选项。否则,您最终可能会a.a.a.a.class在多个库中使用类。

如果您无法控制诸如shadow之类的工具的库发生此问题,则可以使用该工具进行重定位。

于 2019-08-20T07:13:49.467 回答
1

您应该始终为 Java 或其他 JVM 语言中的所有代码添加唯一包的前缀,以创建唯一的完全限定名称,因为具有完全相同的完全限定名称的任何两个类都会导致构建错误。发生这种情况是因为 JVM 仅使用最初保存在单个表中的完全限定名称字符串来实例化系统中的所有类和接口。如果表中的一个类/接口有多个条目,它将不知道该选择哪一个。你可以在这里阅读更多关于它的信息。

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

正如 Proguard文档所述:

-repackageclasses [package_name]

指定通过将所有重命名的类文件移动到单个给定包中来重新打包它们。

于 2020-01-13T15:46:18.647 回答