40

I have a bunch of third party libs that I include in my base application. I cannot control the support library those 3rd party modules include. This makes it hard to have the same version of the android support library in my application.

I know using gradle when I can exclude certain libraries from each dependency:

compile('com.test:lib1:1.0.0') {
    exclude group: 'com.android.support'
}

However there are a ton of support libraries and excluding them all for each one of my 3rd party libraries seems like overkill.

Is there a better way?

Reading this blog post: https://www.devsbedevin.net/android-understanding-gradle-dependencies-and-resolving-conflicts/

It suggests:

configurations.all {
  resolutionStrategy {
    preferProjectModules()
  }
}

However when using that I still get a warning in Android Studio in my gradle file that there are multiple versions of the support library detected.

What do I do if my dependencies depend on different versions of the support library? In either case above I would be forcing the 3rd party libraries to use a specific version of the support library that they were not build with. Which version am I supposed to use? Latest support library? Min support library of all 3rd party dependencies?

Here is a minimal gradle file example showing pulling in 3rd party dependencies that each depend on their own version of the support library.

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.2'

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 17
        targetSdkVersion 25
    }
}

configurations.all {
    resolutionStrategy {
        preferProjectModules()
    }
}

dependencies {
    compile 'com.android.support:support-v13:26.0.0'
    compile 'com.test:lib1:1.0' // depends on support-v13:25.0.0
    compile 'com.test:lib2:1.0' // depends on support-v13:25.2.0
    compile 'com.test:lib3:1.0' // depends on support-v13:25.4.0
    compile 'com.test:lib4:1.0' // depends on support-v13:26.0.0
}

Android studio gives the following warning:

enter image description here

Vaiden
  • 15,728
  • 7
  • 61
  • 91
lostintranslation
  • 23,756
  • 50
  • 159
  • 262
  • Please provide your build.gradle and the dependency tree. – Yuliwee Dec 29 '17 at 18:55
  • does it helps https://stackoverflow.com/questions/20989317/multiple-dex-files-define-landroid-support-v4-accessibilityservice-accessibility?rq=1 –  Jan 02 '18 at 19:02

4 Answers4

44

This is certainly possible. In your projects build.gradle file (the top level build.gradle file) add the following code block:

ext {
    supportlib_version = '26.1.0'
    gps_version = '11.2.0'
}

//Ensure that all dependencies use the same version of the Android Support library
subprojects {
    project.configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support'
                    && !details.requested.name.contains('multidex')) {
                details.useVersion "$supportlib_version"
            }
            if (details.requested.group == 'com.google.android.gms'
                    && !details.requested.name.contains('multidex')) {
                details.useVersion "$gps_version"
            }
        }
    }
}

The following code ensures that the 'com.android.support' dependency version will be equal to $supportlib_version for all dependencies. The same for the 'com.google.android.gms' framework.

Make sure that in your module's build.gradle file you also use these versions for your dependencies. E.g.:

compile "com.android.support:support-v4:$supportlib_version"

Read more about forcing a certain dependency version in the Official Gradle documentation.

Update Google has decoupled library versions. Therefore, forcing a specific version above 15.0.0 may not work. Instead, you can allow a limited range of versions. The example below allows any version higher than 15.0.0 but lower than 16.

gps_version = '[15.0.0, 16.0.0)'
Mdlc
  • 7,128
  • 12
  • 55
  • 98
  • 1
    Sure but what if the support library version that my dependencies were built with are not compatible with the support library I am using. Seems dangerous. And doesn't referProjectModules() do the same thing? – lostintranslation Jan 02 '18 at 20:26
  • @lostintranslation Obviously, if you override the support library versions of your dependencies, there is a chance of compatibility issues. But using multiple versions of a support library in one project, this may also load to bugs. Since using a high support library version should resolve the former (as newer versions are backward compatible), I would recommend the former. – Mdlc Jan 02 '18 at 20:55
  • this Answer saved my day :P – Darshan Jul 15 '18 at 07:08
2

First case: You have compatible libs wich already updated their own internal libs, No problem here.

Second case: You have libs in your project which have higher version than other libs contained internal to other libs, and these libs can be updated to new version with no such problem, Also No problem here.

Worst case: You have libs in your project which have higher version than other libs contained internal to other libs, and these libs doesn't have a new version that has already updated there internal libs, suggested solutions for that:

  1. Download that library and include it to your app as project implementation project(':library') and update their internal libs.
  2. OR Use other library instead.

Don't forget to use ./gradlew app:dependencies to check your dependencies.

Also I believe should be there someway to do that automatically.

  • 1
    So if I depend on lib1 and lib2. lib1 has support support-v13:25.2.0, and lib2 has support-v13:25.4.0. Then the one and only solution is download lib1 locally and update its version of the support library to 25.4.0? So many different libs depend on different versions of the support library, why even use a central repo at that point? – lostintranslation Dec 29 '17 at 19:35
  • @lostintranslation You do that only if *lib* 1 it self doesn't have higher version. –  Dec 29 '17 at 19:36
  • `many different libs depend on different versions of the support library` I don't think so. –  Dec 29 '17 at 19:39
  • 2
    HA, are you kidding? You are saying that all developers that make a library always depend on the same version of the support library? No way. I can find 30 open source projects that depend on older versions of the support library. – lostintranslation Dec 29 '17 at 19:41
  • 1
    Sure, but I have 20 dependencies, and they don't always update their project to the latest support library. Lets say one of those dependencies uses support-library:25.4.0 and all others use 25.2.0. You are saying that I should pull all 19 other projects locally and update their support library to version 25.4.0. Why even use a central repo at that point. There has got to be a better way. – lostintranslation Dec 29 '17 at 19:46
0

You need to specify dependency, with your desired version, that is causing the conflict before the libs that need it. If you do that these lib will use your specified dependency version.

Example with libs (from warning message) from your screenshot

dependencies {
    compile 'com.android.support:support-v13:26.0.0'
    compile 'com.android.support:support-compat:26.0.0'
    compile 'com.android.support:animated-vector-drawable:26.0.0'
    compile 'com.test:lib1:1.0' // depends on support-v13:25.0.0
    compile 'com.test:lib2:1.0' // depends on support-v13:25.2.0
    compile 'com.test:lib3:1.0' // depends on support-v13:25.4.0
    compile 'com.test:lib4:1.0' // depends on support-v13:26.0.0
}

Continue adding dependencies (that show up in the warning from your screenshot) until there is no longer any warning message about different library versions.

Mateusz
  • 681
  • 5
  • 9
  • 1
    Please re-read the question, not what I am asking at all. In your answer android studio will still warn you of multiple different versions of the support library. – lostintranslation Jan 02 '18 at 20:27
  • I answered one of your questions, which is: However there are a ton of support libraries and excluding them all for each one of my 3rd party libraries seems like overkill. Is there a better way? – Mateusz Jan 02 '18 at 20:30
  • @lostintranslation I've created new project to confirm that my answer is correct and I recommend you do the same. I did gradle sync with 2 different build.gradle file [build1.gradle](https://pastebin.com/VDBmNyqE), [build2.gradle](https://pastebin.com/XYQFUp0b). After sync with build1.gradle AS did show up warning about different versions, but after sync with build2.gradle it didnt because I specified all dependencies from used lib. – Mateusz Jan 02 '18 at 20:46
  • I think you just didn't specify all dependencies from your libraries. – Mateusz Jan 02 '18 at 20:51
0

Make the targetsdkversion 26 and also in your gradle make changes to 26 or u can change your compilesdk version to 25 and change your relevant dependecies to 25

Santanu Sur
  • 10,997
  • 7
  • 33
  • 52