6

I recently migrated a project from Eclipse/Ant to Android Studio/Gradle. I am able to successfully build a signed release version of the project with proguard enabled. However, while testing the release version, I'm getting crashes from certain library projects and jars (which work fine when building a debug version).

For example, when attempting to upload a file to Dropbox (a jar dependency), I get the following error:

java.lang.IncompatibleClassChangeError: interface not implemented
   at com.dropbox.client2.session.AbstractSession.sign(SourceFile:238)
   at com.dropbox.client2.DropboxAPI.putFileRequest(SourceFile:2199)
   at com.dropbox.client2.DropboxAPI.putFileOverwriteRequest(SourceFile:1571)
   at com.dropbox.client2.DropboxAPI.putFileOverwrite(SourceFile:1537)

Also, when attempting to sign into Box (a library project dependency), I get the following error:

java.lang.NoSuchMethodError: org.apache.http.conn.params.ConnManagerParams.setMaxTotalConnections
   at com.box.restclientv2.BoxBasicRestClient.()
   at com.box.boxjavalibv2.BoxRESTClient.()
   at com.box.boxjavalibv2.BoxClient.createRestClient()
   at com.box.boxjavalibv2.BoxClient.()
   at com.box.boxandroidlibv2.BoxAndroidClient.(SourceFile:49)
   at com.box.boxandroidlibv2.activities.OAuthActivity.startOAuth(SourceFile:71)
   at com.box.boxandroidlibv2.activities.OAuthActivity.onCreate(SourceFile:52)

I have other jars and library projects that work just fine...

Again, there are no issues with either of these when building a gradle debug build (no proguard). I was also able to create a release build with proguard enabled using ant without any issues (able to sign into both Dropbox and Box).

Any ideas?

ashughes
  • 7,155
  • 9
  • 48
  • 54
  • Well it appears adding the proguard rule `-keep class org.apache.http.** { *; }` has "fixed" both of these crashes. I'm still a bit uncomfortable with this, as this proguard rule was not needed when I built the project with Ant. This rule does make sense why it fixed the `NoSuchMethodError` for the Box crash, but not the Dropbox crash. Can anyone provide an explanation? – ashughes Mar 14 '14 at 06:03

2 Answers2

4

You appear to be including a version of the org.apache.http library. In principle, this library is already part of the Android runtime android.jar, so you shouldn't add it to your project. ProGuard is probably printing warnings about these duplicate classes.

In practice, it may be a newer version of the library, and some of your code may be using additional classes from this version. You then probably should leave the names of the classes, fields, and methods untouched, to avoid introducing (additional) conflicts:

-keep class org.apache.http.** { *; }

A build process may filter out the classes, or it may be adding the above line, but I don't think the default Android builds currently do either.

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

You need to -keep Proguard from removing or renaming all the class and method names that it can't determine are referenced from code that it doesn't processes, that are referenced via reflection (e.g. XML references), etc.

Keeping all apache classes may keep more than necessary (which is OK) but it may not be enough to fix all the Proguard issues.

It's good to ask why it worked from your ant build without this -keep. Maybe the ant build didn't actually call Proguard (ant is tricky), maybe it used a different Proguard data file, or maybe the relevant libraries changed in the meantime. You can debug that by listing hypotheses and testing them. E.g. if you put a malformed command in the Proguard data file then run the ant build, you can tell whether it actually runs Proguard or not.

Jerry101
  • 12,157
  • 5
  • 44
  • 63
  • 1
    Comparing the builds is a good idea. You can let ProGuard write out the configuration that it uses with `-printconfiguration conf.txt`. That will include the input jars and library jars. – Eric Lafortune Mar 26 '14 at 00:44
  • Jerry101, I understand how proguard works, and I'm positive proguard was running on my ant build (I've had many missing proguard rules, which I've had to hunt down in the past). @EricLafortune Thanks. I'll see if I can compare the configurations. I still think there's something fishy going on with the new Android gradle build system. It seems like it's not "protecting" parts of the Android SDK from proguard (such as the org.apache.http package). I've file a bug report here: https://code.google.com/p/android/issues/detail?id=67166 – ashughes Apr 05 '14 at 18:35
  • It's great that you're debugging this and filed a bug. More debugging ideas: Create a minimal test project that calls apache.http to reproduce the problem. Use Proguard settings printconfiguration, dump, and verbose to see what it's doing and exactly what config it uses. Compare the actual config to an ant build's. Since the typical gradle build uses a standard proguard config file + a project-specific config file, the problem could be in the former, although if this library is in the OS instead of included in the APK, it's still fishy. – Jerry101 Apr 05 '14 at 22:32