Proguard和XmlPullParser的问题

6
我在使用Proguard和一些库开发安卓项目时遇到了XmlPullParser冲突问题,但是无论我怎么做都解决不了。这里是我使用的库:

JacksonParser,包括:
- Jackson-all.1.6.4.jar
- Joda-time.1.6.2.jar
- jsr311-api-1.0.jar
- stax2-api-3.0.0.jar

XStream,包括:
- xpp3_min-1.1.4c.jar
- xstream-for-android-1.0.0.jar

还有其他一些库,但它们不是问题的关键。这些库似乎是导致问题的源头。

具体而言,出现以下问题:

优化
如果进行优化,会显示"conversion to dalvik failed with 1"。关于这个问题有一个专门的帖子,链接为:"Conversion to Dalvik format failed with error 1" on external JAR,它指向了方向:重复的XmlPullParser类。这很有道理,因为XStream使用app3_min-1.1.4c.jar,其中包含了一个XmlPullParser,比android.jar中的那个功能更好/更多。因此,我尝试从android.jar中使用通配符xmlpull **移除:
-libraryjars <java.home>/lib/rt.jar;C:/Android/platforms/android-9/android.jar(!org/xmlpull/v1/**)

我也尝试了明确地删除它们:

-libraryjars <java.home>/lib/rt.jar;C:/Android/platforms/android-9/android.jar(!org/xmlpull/v1/XmlPullParser.class,!org/xmlpull/v1/XmlPullParserException.class,!org/xmlpull/v1/XmlPullParserFactory,!org/xmlpull/mxp1/MXParser)

但是两种修复方法都没有帮助。

但是等等,还有更多的问题(都集中在同一个问题上,所以我认为如果解决了这个问题,其他问题也会消失)。

混淆

如果我尝试混淆,就会出现以下运行时错误:

java.lang.NoSuchMethodError: android.content.res.XmlResourceParser.s
looking this up in the mapping, i get: .s = abstract int next()

所以它缺少了next()方法。那么为什么会缺少这个方法呢?我不理解。我甚至尝试过这样做:

-keep class android.content.res.XmlResourceParser { int next(); }

为了确保该方法得到保留,但我仍然遇到了相同的问题。
缩小也似乎失败了。应用程序启动后没有任何进展,它只是一直尝试启动第一个活动并给我一个无用的错误。不过我现在还不太担心这个问题,如果我能让混淆和优化工作正常,我可以不使用缩小功能。
更多信息:
作为参考,我已经尝试过两种引用库的方式,第一种是使用injars:
-injars ReferencedAssemblies/XStream/xpp3_min-1.1.4c.jar(!META-INF/MANIFEST.MF)
-injars ReferencedAssemblies/JacksonParser/jackson-all-1.6.4.jar(!META-INF/MANIFEST.MF,!META-INF/ASL2.0,!META-INF/LICENSE,!META-INF/NOTICE)
-injars ReferencedAssemblies/JacksonParser/joda-time-1.6.2.jar(!META-INF/MANIFEST.MF)
-injars ReferencedAssemblies/JacksonParser/jsr311-api-1.0.jar(!META-INF/MANIFEST.MF)
-injars ReferencedAssemblies/JacksonParser/stax2-api-3.0.0.jar(!META-INF/MANIFEST.MF)
-injars ReferencedAssemblies/XStream/xstream-for-android-1.0.0.jar(!META-INF/MANIFEST.MF)

这甚至无法构建。

我还做了这个:

-libraryjars <java.home>/lib/rt.jar
  ;C:/Android/platforms/android-9/android.jar(!org/xmlpull/v1/**)
  #;C:/Android/platforms/android-9/android.jar(!org/xmlpull/v1/XmlPullParser.class,!org/xmlpull/v1/XmlPullParserException.class,!org/xmlpull/v1/XmlPullParserFactory,!org/xmlpull/mxp1/MXParser)
  ;ReferencedAssemblies/JacksonParser/jackson-all-1.6.4.jar(!META-INF/MANIFEST.MF,!META-INF/ASL2.0,!META-INF/LICENSE,!META-INF/NOTICE)
  ;ReferencedAssemblies/JacksonParser/joda-time-1.6.2.jar(!META-INF/MANIFEST.MF)
  ;ReferencedAssemblies/JacksonParser/jsr311-api-1.0.jar(!META-INF/MANIFEST.MF)
  ;ReferencedAssemblies/JacksonParser/stax2-api-3.0.0.jar(!META-INF/MANIFEST.MF)
  ;ReferencedAssemblies/XStream/xpp3_min-1.1.4c.jar(!META-INF/MANIFEST.MF)

这是我能做到的最远的进展,如果我不进行优化,我就能导出一个APK。
我还做了以下操作:
-dontwarn org.xmlpull.v1.**

由于这似乎是一个已知的问题(请参见上面的链接),有人知道发生了什么或者如何解决它吗?我有一种感觉,这可能与我同时使用XStream和JacksonParser有关,也许其中一个JacksonParser库中还有XmlPullParser?问题是,这可以解释优化错误,但不能解释混淆错误。对于后者我毫无头绪。即使我明确保留了该方法,为什么它仍然找不到呢?

谢谢大家。

4个回答

10

这对我有用:

-dontwarn org.xmlpull.v1.**
-dontnote org.xmlpull.v1.**
-keep class org.xmlpull.** { *; }

这对我实际起作用了。至少目前看来我没有任何问题。在我的应用程序中更新了Google Play服务的一部分到最新版本并运行proguard后,我遇到了这个问题。 - Armando

2

您的ProGuard配置和构建过程似乎混淆了程序JAR和库JAR。

对于ProGuard,您可以使用-injars指定所有列出的JAR作为输入JAR。它们处理后的版本将出现在输出JAR(-outjars)中。

您确实可以通过过滤android.jar中的重复xmlpull类来避免警告。如果输入JAR中存在任何重复项,则ProGuard还会打印出警告。然后,您可以从中过滤掉这些重复项。

您不应将<java.home>/lib/rt.jar指定为库JAR,因为此JAR在Android设备上也不存在作为库。其中一些列出的JAR依赖于它,因此它们的部分内容与Android运行时不完全兼容。避免有关冒犯性类的警告的最清洁的解决方案是从相应的输入JAR中过滤掉它们(例如使用一个过滤器!com/thoughtworks/xstream/converters/extended/ColorConverter.class)。或者,您可以直接关闭这些警告(例如-dontwarn com.thoughtworks.xstream.converters.extended.ColorConverter)。

对于Dalvik编译器,您只需指定已处理的输出JAR,而无需指定任何进入它的程序JAR。否则,您将获得重复的类:一些未经处理的副本和一些部分混淆的副本。它们不融合并导致Error1和NoSuchMethodErrors。


0

0

在Android上,XML解析可能会是一项真正的痛点。最近我在尝试使用Jackson XML数据绑定时也遇到了类似的问题。

最终,我使用了Jar Jar Links工具将我正在尝试使用的库中出现冲突的类移动到一个新的包名称中,这个新的包名称不会与Android平台类产生冲突:

http://code.google.com/p/jarjar/

您可以告诉Jar Jar Links查找我们提供的XML库JAR文件中与Android冲突的命名空间(即javax.xml.stream.*),并让JarJar将它们重命名为不会冲突的名称(即edu.usf.cutr.javax.xml.stream.*)。这样,Android就能够接受不会冲突的库,而无需出现Conversion to Dalvik format failed with error 1的错误。

这里有一个zip文件,其中包含我用于批量转换所需的XML库文件。

包含generate_android_jarsv21.bat批处理文件,可自动化使用JarJar对多个XML库JAR进行转换过程。

JarJar使用一系列规则来更改JAR文件中的命名空间。以下是我的rules.txt文件的内容,将所有出现的javax.xml.stream.*重命名为edu.usf.cutr.javax.xml.stream.*

rule javax.xml.stream.** edu.usf.cutr.javax.xml.stream.@1

您应该能够按照类似的过程处理您正在使用的XML库。一旦通过将库类移动到新包中解决了包冲突问题,Proguard的其他下游问题也应该得到解决。

我在这里写了一个完整的教程,其中包括有关“修改Android XML库”的更多详细信息:

https://github.com/CUTR-at-USF/SiriRestClient/wiki/Modifying-XML-libraries-for-Android


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接