15

I get this error when I Run->app for an Android application in Android Studio

UNEXPECTED TOP-LEVEL EXCEPTION:
    com.android.dex.DexException: Multiple dex files define Lcom/google/common/annotations/Beta;
...

And here is the output of gradlew -q :app:dependencies

+--- project :shared
+--- com.google.api-client:google-api-client:1.19.0
|    +--- com.google.oauth-client:google-oauth-client:1.19.0
|    |    +--- com.google.http-client:google-http-client:1.19.0
|    |    |    +--- com.google.code.findbugs:jsr305:1.3.9
|    |    |    \--- org.apache.httpcomponents:httpclient:4.0.1
|    |    |         +--- org.apache.httpcomponents:httpcore:4.0.1
|    |    |         +--- commons-logging:commons-logging:1.1.1
|    |    |         \--- commons-codec:commons-codec:1.3
|    |    \--- com.google.code.findbugs:jsr305:1.3.9
|    +--- com.google.http-client:google-http-client-jackson2:1.19.0
|    |    +--- com.google.http-client:google-http-client:1.19.0 (*)
|    |    \--- com.fasterxml.jackson.core:jackson-core:2.1.3
|    \--- com.google.guava:guava-jdk5:13.0
+--- com.google.http-client:google-http-client-gson:1.19.0
|    \--- com.google.code.gson:gson:2.1
+--- com.google.api-client:google-api-client-android:1.19.0
|    +--- com.google.api-client:google-api-client:1.19.0 (*)
|    \--- com.google.http-client:google-http-client-android:1.19.0
|         \--- com.google.http-client:google-http-client:1.19.0 (*)
+--- com.google.http-client:google-http-client-android:1.19.0 (*)
+--- com.google.guava:guava:14.0.+ -> 14.0.1
+--- project :backend-appengine
|    \--- com.google.api-client:google-api-client-android:1.19.0 (*)
+--- com.android.support:appcompat-v7:20.0.0
|    \--- com.android.support:support-v4:20.0.0
|         \--- com.android.support:support-annotations:20.0.0
+--- com.google.android.gms:play-services:5.0.89
\--- com.google.maps.android:android-maps-utils:0.3.+ -> 0.3.1

Here is the dependency block from build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':shared')
    // Add the Google API client library.
    compile(group: 'com.google.api-client', name: 'google-api-client', version: '1.19.0') {
        // Exclude artifacts that the Android SDK/Runtime provides.
        exclude(group: 'com.google.guava')     //-- !!! this does not seem to work !!!
        exclude(group: 'xpp3', module: 'xpp3')
        exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
        exclude(group: 'junit', module: 'junit')
        exclude(group: 'com.google.android', module: 'android')
        exclude(group: 'com.google.http-client', module: 'google-http-client')
    }

    compile('com.google.http-client:google-http-client-gson:1.19.0') {
        exclude module: 'httpclient'
        exclude(group: 'com.google.http-client', module: 'google-http-client')
    }

    compile(group: 'com.google.api-client', name: 'google-api-client-android', version: '1.19.0') {
        exclude(group: 'com.google.android.gms', module: 'play-services')
        exclude group: 'com.google.guava', module: 'guava-jdk5'
    }

   compile(group: 'com.google.http-client', name: 'google-http-client-android', version: '1.19.0') {
        exclude(group: 'com.google.android', module: 'android')
    }

    // This is used by the Google HTTP client library.
    compile(group: 'com.google.guava', name: 'guava', version: '14.0.+')

    //-- endpoints
    dependencies {
        compile project(path: ':backend-appengine', configuration: 'android-endpoints')
    }

    compile 'com.android.support:appcompat-v7:20.0.0'
    compile ('com.google.android.gms:play-services:5.0.89') {
        exclude(group: 'com.android.support', module: 'support-v4')
    }
    compile ('com.google.maps.android:android-maps-utils:0.3.+') {
        exclude(group: 'com.google.android.gms', module: 'play-services')
    }   
}
aez
  • 2,406
  • 2
  • 26
  • 46

4 Answers4

13

For those who are using Google Cloud Endpoints in Android app:

compile(project(path: ':backend', configuration: 'android-endpoints')) {
    exclude(module: 'guava-jdk5')
}

Where backend is name of your module with AppEngine app.

In every other case just look for guava-jdk5 transitive dependency and exclude it.

tomrozb
  • 25,773
  • 31
  • 101
  • 122
10

The com.google.common.annotations package seems to be part of Guava. I see it in the dependencies twice in slightly different variations: once as part of Google API Client, once as your own dependency:

+--- com.google.api-client:google-api-client:1.19.0
|    \--- com.google.guava:guava-jdk5:13.0

and

+--- com.google.guava:guava:14.0.+ -> 14.0.1

So the cause of this error is that you have the same classes defined in multiple dex files (in different variations of the Guava library) being included by your other dependencies. You'll need to find a way to exclude these duplicated dependencies, or possibly just ensure that you use the same version across all dependencies.

One thing you could try is to exclude the guava module from one of the dependencies. So, where you have the API Client module defined, add an exclusion rule for the guava module:

compile ('com.google.api-client:google-api-client:1.19.0') {
    exclude group: 'com.google.guava', module: 'guava-jdk5'
}

I can't guarantee this won't cause problems for the Google API Client library (since they are two different versions of Guava) but it's worth a try.

EDIT: From your depdencies, try changing this:

compile(group: 'com.google.api-client', name: 'google-api-client', version: '1.19.0') {
    // Exclude artifacts that the Android SDK/Runtime provides.
    exclude(group: 'com.google.guava')     //-- !!! this does not seem to work !!!

to:

compile(group: 'com.google.api-client', name: 'google-api-client', version: '1.19.0') {
    exclude(group: 'com.google.guava', module: 'guava-jdk5')

The google-api-client-android library doesn't actually contain Guava -- I didn't realize you had two similarly named dependencies in there.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • Thanks kcoppock. I think you must be right, but no matter how I try, I cannot exclude the guava module from the com.google.api-client compile. Why would this be so? I use: compile(group: 'com.google.api-client', name: 'google-api-client', version: '1.19.0') { exclude(group: 'com.google.guava') } and every other exclude possibility I can think of but it never gets excluded – aez Sep 23 '14 at 01:21
  • However, kcoppock, I know you are correct, because I commented out the second guava compile (14.0) and I can build. But still, I want to be able to exclude the first guava module, but grade doesn't seem to allow it. Any ideas why? – aez Sep 23 '14 at 01:26
  • Are you sure you changed your dependency *exactly* as shown above? I just tried it myself, and without my exclude line, it fails to assemble just like yours. With the exclude line, it succeeds. – Kevin Coppock Sep 23 '14 at 01:35
  • As far as I can tell, you put your exclude with the google-api-client-ANDROID module, but the guava module we're trying to exclude is with the earlier google-api-client module at the top. Therefore when I put the exclude exactly as you have it with exactly the compile you show, it does nothing, because there is no guava with that particular compile. And indeed, it fails to assemble again. – aez Sep 23 '14 at 01:58
  • Can you post your entire dependencies block? – Kevin Coppock Sep 23 '14 at 01:59
  • See my update. I misread your dependencies (since you have two similar libraries api-client and api-client-android). The android library doesn't contain the Guava dependency -- it's the standard api-client library that does. – Kevin Coppock Sep 23 '14 at 02:21
  • Thanks, but that latest exclude also doesn't work. It simply won't exclude the guava module. Rerunning gradle -q dependencies shows the guava module even with the latest exclude. – aez Sep 23 '14 at 02:41
  • In any case, you've worked hard enough for this question. If you edit it to just note that I had two versions of the same module and that one of them needed to be excluded, I will accept your answer. Then I'll follow up and post another question on the exclude problem. Thanks – aez Sep 23 '14 at 03:18
  • Updated. :) Sorry I couldn't get a total solution for you, but maybe it'll get you on the right track. – Kevin Coppock Sep 23 '14 at 04:53
  • if you think the question is a worthwhile part of the forum, please consider upvoting it. – aez Sep 23 '14 at 10:35
  • see my solution before, i believe that is the more fundamentally correct approach – Creos Feb 23 '16 at 02:52
6

Here is the correct solution solution, worked for me. Excluding the guava-jdk5 dependency module from each individual import is counterproductive (for me it didn't work because I had some internal dependencies coming from my backend on which my app depends, and this exposes the real issue with this approach).

The following solved the problem and is the recommended approach:

configurations {
    all*.exclude group: 'com.google.guava', module: 'guava-jdk5'
}

Source: https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.Configuration.html

Creos
  • 2,445
  • 3
  • 27
  • 45
5

It seems you can't use both guava and guava-jdk5 in the same project. Guava-jdk5 is still being maintained, so consider changing your project's guava reference to guava-jdk5:

compile 'com.google.guava:guava-jdk5:17.0'
PacificSky
  • 3,422
  • 2
  • 25
  • 24
  • Only this soln worked for me. Excluding guava-jdk5 from the endpoints library - as suggested above - sounded like a more attractive solution but didn't work. – Tom Apr 28 '15 at 16:09