【问题标题】:Problem with Proguard and XmlPullParserProguard 和 XmlPullParser 的问题
【发布时间】:2011-07-21 18:31:42
【问题描述】:

我在使用带有一些库的 Proguard 的 Android 项目上遇到了一些麻烦。具体来说,我遇到了 XmlPullParser 冲突,无论我做什么,我似乎都无法解决它。以下是我正在使用的库:

JacksonParser,包括:

  • 杰克逊-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

还有其他的,但它们不是问题。这些似乎是我们问题的罪魁祸首。

具体来说,问题是:

优化

如果我进行优化,我会得到“转换为 dalvik 失败,结果为 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?问题是,这可以解释优化错误,但不能解释混淆错误。我不知道那个。为什么它不会找到那个方法,即使如果我明确地保留了它?

谢谢大家。

【问题讨论】:

    标签: android proguard


    【解决方案1】:

    这对我有用:

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

    【讨论】:

    • 这实际上对我有用。至少到目前为止我似乎没有任何问题。在将我的应用中的部分 Google Play 服务更新到最新版本并运行 proguard 后,我遇到了这个问题。
    【解决方案2】:

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

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

    您确实可以通过将它们从 android.jar 中过滤掉来避免有关重复 xmlpull 类的警告。如果输入 jar 中有任何重复项,ProGuard 还将打印出警告。然后,您也可以过滤掉这些重复项。

    您不应将&lt;java.home&gt;/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。

    【讨论】:

      【解决方案3】:

      要让库类优先并关闭Proguard,请将其放在main-rules.xml中(但先复制一部分到build.xml):

                  -libraryjars ${android.libraryjars}(!org/xmlpull/v1/XmlPullParser.class,!org/xmlpull/v1/XmlPullParserException.class)
      

      您还会遇到 XStream 的其他问题,请参阅: Proguard and XStream with omitField() on Android

      整个故事:https://plus.google.com/112617873637231221858/posts/YxWrEJRMSo4

      【讨论】:

        【解决方案4】:

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

        我最终使用工具 Jar Jar Links 将我尝试使用的库中的冲突类移动到与 Android 平台类不冲突的新包名称:

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

        您可以告诉 Jar Jar Links 在我们提供的与 Android 冲突的 XML 库 JAR 文件中查找命名空间(即javax.xml.stream.*),并让 JarJar 将它们重命名为不冲突的名称(即 @ 987654330@)。然后,Android 将接受在没有 Conversion to Dalvik format failed with error 1 的情况下不冲突的库。

        这是一个zip file,其中包括我用来批量转换所需的 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

        【讨论】:

          猜你喜欢
          • 2011-07-17
          • 1970-01-01
          • 2016-01-20
          • 2016-02-11
          • 1970-01-01
          • 1970-01-01
          • 2011-01-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多