5

I'm having a bit of trouble on an Android project using Proguard with some libraries. Specifically, i'm having an XmlPullParser collision, and no matter what i seem to do, i can't seem to solve it. Here are the libraries I am using:

JacksonParser, includes:

  • Jackson-all.1.6.4.jar
  • Joda-time.1.6.2.jar
  • jsr311-api-1.0.jar
  • stax2-api-3.0.0.jar

XStream, which includes:

  • xpp3_min-1.1.4c.jar
  • xstream-for-android-1.0.0.jar

There are also others, but they're a non-issue. These seem to be the culprit of our problems.

Specifically, the issues are:

Optimization

if i do an optimization, i get "conversion to dalvik failed with 1". There is a post specifically about this at "Conversion to Dalvik format failed with error 1" on external JAR, which pointed me in the direction of having a duplicate XmlPullParser class. This makes sense, since XStream uses app3_min-1.1.4c.jar, which includes an XmlPullParser that has better/additional functionality than the one included in the android.jar. as such, i've tried a wildcard xmlpull** removal from android.jar:

-libraryjars <java.home>/lib/rt.jar;C:/Android/platforms/android-9/android.jar(!org/xmlpull/v1/**)

and i've also tried explicitly removing them:

-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)

but neither fix has helped.

but wait, there's more (all centered around the same issue though, so i think if i solve this one, the others go away).

Obfuscation

If i try to obfuscate, i get the following runtime error:

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

so it's missing the next() method. so why is that method missing? i don't understand. i even tried doing this:

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

to make sure that method gets preserved, but still i get the same issue.

Shrinking

Shrinking also seems to fail. the app launches but never gets anywhere, it just keeps trying to launch the first activity over and over and giving me a useless error. i'm not so worried about this yet though, i can live without shrinking, if i can get obfuscation and optimization working.

More Info

As a point of reference, i've tried to reference my libraries two ways, the first is using 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)

this won't even build.

i've also done this:

-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)

this gets me the furthest, i'm able to export an APK if i don't optimize.

i've also done this:

-dontwarn org.xmlpull.v1.**

since this seems to be a known issue (see previous link)

Anyone have any idea of what's going on here or how i solve it? i have a feeling that this has something to do with the fact that i'm using both XStream and JacksonParser, and perhaps one of the JacksonParser libraries also has an XmlPullParser in it? The thing is, that would explain the optimization error, but not the obfuscation error. i have no idea on that one. why would it not be finding that method, even if i've explicitly preserved it?

thanks all.

Community
  • 1
  • 1
bryan costanich
  • 1,719
  • 6
  • 20
  • 33

4 Answers4

10

This works for me:

-dontwarn org.xmlpull.v1.**
-dontnote org.xmlpull.v1.**
-keep class org.xmlpull.** { *; }
stefan
  • 1,336
  • 3
  • 21
  • 46
  • This actually worked for me. At least it seems I have no issues so far. I had this issue after updating part of Google Play Services in my app to the latest to date and running proguard. – Armando May 22 '15 at 21:03
2

Your ProGuard configuration and build process seem to be mixing up program jars and library jars.

For ProGuard, you can probably specify all the listed jars as input jars (with -injars). Their processed versions will end up in the output jar (-outjars).

You can indeed avoid warnings about duplicate xmlpull classes by filtering them out of android.jar. ProGuard will also print out warnings should there be any duplicates in the input jars. You can then filter out those duplicates as well.

You should not specify <java.home>/lib/rt.jar as a library jar, since this jar is not present as a library on Android devices either. Some of the listed jars depend on it though, so at least parts of them are not entirely compatible with the Android runtime. The cleanest solution to avoid warnings about offending classes is to filter them out of the corresponding input jars (e.g. a filter !com/thoughtworks/xstream/converters/extended/ColorConverter.class). Alternatively, you can bluntly switch off these warnings (e.g. -dontwarn com.thoughtworks.xstream.converters.extended.ColorConverter).

For the Dalvik compiler, you should only specify the processed output jar, not any of the program jars that went into it. Otherwise, you will get duplicate classes: some unprocessed copies and some partly obfuscated copies. They don't blend and lead to Error1 and NoSuchMethodErrors.

Eric Lafortune
  • 45,150
  • 8
  • 114
  • 106
0

XML parsing can be a real pain on Android. I recently ran into similar issues when trying to use Jackson XML data binding on Android.

I ended up using the tool Jar Jar Links to move the conflicting classes in the libraries I was trying to use to a new package name that doesn't conflict with the Android platform classes:

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

You can tell Jar Jar Links to find the namespaces in the XML library JAR files that we provide that conflict with Android (i.e., javax.xml.stream.*), and have JarJar rename them to something that doesn't conflict (i.e., edu.usf.cutr.javax.xml.stream.*). Android will then accept the libraries that doesn't conflict without the Conversion to Dalvik format failed with error 1.

Here's a zip file that includes files I used to do a batch conversion of the XML libraries I needed, which were:

  • StAX API - JSR 173 API interface definitions. Also see Wikipedia StAX entry for more info.
  • StAX2 API - Experimental expansion of the original StAX API used by Aalto
  • Aalto - StAX 1 and 2 XML parser implementation
  • jackson-dataformat-xml - integrates the above XML parser APIs and implementations with the core Jackson project

The generate_android_jarsv21.bat batch file is included to automate the conversion process using JarJar for multiple XML library JARs at once.

JarJar uses a series of rules to change the namespaces in the JAR files. Here's the contents of my rules.txt file that renames all occurences of javax.xml.stream.* to edu.usf.cutr.javax.xml.stream.*:

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

You should be able to follow a similar process for the XML libraries you're working with. Once the collision in packages is resolved by moving the library classes to a new package, the other down-stream issues with Proguard should resolve themselves.

I wrote a full tutorial here that includes more detail on "Modifying XML libraries for Android":

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

Sean Barbeau
  • 11,496
  • 8
  • 58
  • 111
0

To let library classes take precedence and shut up Proguard, put this in main-rules.xml (but copy a part to build.xml first):

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

You'll run into other problems with XStream as well, see: Proguard and XStream with omitField() on Android

For the whole story: https://plus.google.com/112617873637231221858/posts/YxWrEJRMSo4

Community
  • 1
  • 1
pjv
  • 10,658
  • 6
  • 43
  • 60