我创建了两个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'不是库类:混淆后,所有库类名称均保持不变,并且R.8将a.class添加到程序包中。 我阅读了R8文档,未发现有关此问题的任何信息。 有什么方法可以解决这个问题而无需在我的一个库中重载该软件包?
答案 0 :(得分:1)
创建两个库时,最好的做法是使用两个不同的名称空间,否则,当“偶然地”将具有相同名称的类添加到两个类时,即使不使用R8,也存在重复类的可能性。因此,在您的情况下,请使用com.example.test1
和com.example.test2
。
根据您的用例,不将R8应用于库,而仅将R8应用于包括两个库的最终应用程序也是一个更好的选择。缩小库主要是为了减小发行版的大小,并重新命名内部结构,以避免库用户(偶然或有意地)依赖内部结构,内部结构可能会在库版本之间发生变化。
在收缩库时,您还需要考虑选项-keeppackagenames
,以确保所有重命名的类都位于库包中。否则你可能会上课a.a.a.a.class
在多个库中。
如果此问题发生在您无法控制shadow之类的工具的库中,则可用于重定位。
答案 1 :(得分:0)
您应该始终使用 unique 软件包在Java或其他JVM语言中为所有代码添加前缀,以创建唯一的fully qualified name,因为具有完全相同的完全限定名称的任何两个类都将导致建立错误。发生这种情况是因为JVM仅使用最初保存在单个表中的标准名称字符串来实例化系统中的所有类和接口。如果该表的一个类/接口有多个条目,它将不知道要选择哪个条目。您可以详细了解here。
正如我在答案here中所述,与混淆相关的冲突的最佳解决方案是在每个库的-repackageclasses com.example:test#.ofs
文件中使用proguard-rules
,同时用{替换#
{1}}和1
分别。这会将所有混淆的类移到2
包中,而所有未混淆的类将保留在其原始包中,并确保没有冲突。
Proguard documentation指出:
-重新包装类[package_name]
指定通过将所有重命名的类文件移动到单个给定的包中来重新打包。