12

I have the following code in the build.gradle in the app module of my Android project

implementation('com.google.firebase:firebase-core:16.0.1', {
    exclude group: 'com.android.support'
})
implementation('com.google.firebase:firebase-database:16.0.1', {
    exclude group: 'com.android.support'
})
implementation('com.google.firebase:firebase-auth:16.0.1', {
    exclude group: 'com.android.support'
})
implementation('com.google.firebase:firebase-crash:16.0.1',  {
    exclude group: 'com.android.support'
})

The firebase libraries all contain a conflicting version of the android support library which I am using and so I need to exclude it to prevent the build warning

All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 27.1.1, 26.1.0. Examples include com.android.support:animated-vector-drawable:27.1.1 and com.android.support:support-media-compat:26.1.0 less... (Ctrl+F1) 
There are some combinations of libraries, or tools and libraries, that are incompatible, or can lead to bugs. One such incompatibility is compiling with a version of the Android support libraries that is not the latest version (or in particular, a version lower than your targetSdkVersion).

Is there a way I can group these implementation statements together so I only need to write one exclude statement?

EDIT

My specific solution based on Cris' answer

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'com.android.support') {
            details.useVersion '27.1.1'
        }
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.google.firebase:firebase-core:16.0.1'
    implementation 'com.google.firebase:firebase-database:16.0.1'
    implementation 'com.google.firebase:firebase-auth:16.0.1'
    implementation 'com.google.firebase:firebase-crash:16.0.1'
}
Adam
  • 2,167
  • 5
  • 19
  • 33

2 Answers2

13

As stated on the official gradle documentation, you can achieve that as follows:

configurations {
    implementation {
        exclude group: 'javax.jms', module: 'jms'
        exclude group: 'com.sun.jdmk', module: 'jmxtools'
        exclude group: 'com.sun.jmx', module: 'jmxri'
    }
}

Another option, is to force a specific version of the group of libraries, support in this case. This is also covered by the official documentation

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'org.gradle') {
            details.useVersion '1.4'
            details.because 'API breakage in higher versions' 
            //note that details.because requires Gradle version 4.6 or higher
        }
    }
}
Cris
  • 774
  • 9
  • 32
  • 1
    This appears to also cause the support library itself to be excluded. – Adam Sep 04 '18 at 11:41
  • @Moses the answer has been edited to add an option to force a specific version – Cris Sep 04 '18 at 11:51
  • the `details.because` method causes the following exception `No signature of method: org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DefaultDependencyResolveDetails.because() is applicable for argument types: (java.lang.String) values: [Prevent different versions of android support library contained in other dependencies from conflicting with the one defined in this build.gradle] Possible solutions: isCase(java.lang.Object), use([Ljava.lang.Object;)` but after removing that line it seems to work fine. – Adam Sep 04 '18 at 11:59
  • @Moses `details.because` was added on version 4.6, according to the [release notes](https://docs.gradle.org/4.6/release-notes.html), are you using an older version? – Cris Sep 04 '18 at 12:10
  • I'm using the most up to date version Android supports. That usually lags behind the latest version of gradle. – Adam Sep 04 '18 at 12:46
  • links broken... – RedDeath Sep 16 '21 at 13:09
0

I usually take care of this error by putting this in the gradle file:

// use default version for all support repositories
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion 'PUT_THE_VERSION_YOU_WANT' //latest would be 28.0.0-rc02
            }
        }
    }
}

You might have to add multiDexEnabled true inside android. What this basically does is force everything to use a specific version, so they won't have any conflicts.

Jacob Celestine
  • 1,758
  • 13
  • 23