1

I'm using Tommy Buonomo's excellent library (here on GitHub and this SO question where he introduced it) to add a position indicator to a ViewPager, however I am getting a gradle error about support libraries versions which raises a bigger question for me.

The specific error is:

Error:(39, 20) All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 27.0.0, 25.3.1. Examples include 'com.android.support:support-compat:27.0.0' and 'com.android.support:animated-vector-drawable:25.3.1'

(Note that this is flagged as an Error by Android Studio BUT the app still compiles and runs.)

The bigger question this raises is how do you properly handle conflicts in support library versions like this?

I have added the library simply by adding:

compile 'com.tbuonomo.andrui:viewpagerdotsindicator:1.0.1'

to my dependencies in my app level build.gradle and as I say everything is working well except for the error.

I'd like to keep my app as error and warning free as possible so I'd like to understand what I can do to resolve this.

This is the first time I have used a third party library in one of my projects so this is the first time I have encountered this specific issue.

So, some questions.

  1. Must a library developer create various versions of their library that target specific other support library versions or can they simply create one library that supports all versions up to a specific version? (It would seem impractical to have to create specific versions as you don't know what versions a library user is going to be using).

  2. Is a user usually able to change the version of other support libraries that the third-party library calls? I cannot seem to find anywhere in the external libraries section of the project tree that would let me do this for Tommy's library so I assume many libraries are like this.

  3. Is the only option to wait for the library developer to create a new version that uses the same API level support libraries that my app uses? (Or to change the support library version that my app uses).

  4. Would another option be to fork the library on github and change the support library versions it uses in the new fork? This then raises the issue of learning how to compile and use libraries and to republish them for others to use (maybe as a pull request to the original author so that they could incorporate the changes - this would be most in the spirit of Tommy having released the library anyway) - and would also require an understanding of all of questions 1-3.

I feel like having got this error I have opened a can of worms here, but I would like to understand more about how this should be fixed if I am to do things properly.

(FYI, I am building my app with compile and target SDK v27 in order to follow best practice of targetting latest API level. Tommy's library already has a pull request to support API v26 which is awaiting action)

Ashish Ranjan
  • 5,523
  • 2
  • 18
  • 39
Fat Monk
  • 2,077
  • 1
  • 26
  • 59

2 Answers2

4

You can force the dependencies to use specific version of support library, try adding this in your project level build.gradle file:

subprojects {
    project.configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support'
                    && !details.requested.name.contains('multidex') ) {
                details.useVersion "yourSupportLibVersion"
            }
        }
    }
}

If you're using support library version 27.0.0 replace yourSupportLibVersion with 27.0.0

Explanation :

  • Why're we using subprojects?

    In a multi-project gradle build, you have a root project and the subprojects. The root project is where the build starts from. Everything else, either added as a dependency in gradle or external libraries added manually, will be processed as a subproject by gradle.

  • What's ResolutionStrategy?

    Quoting from the docs, ResolutionStrategy defines the strategies around dependency resolution. For example, forcing certain dependency versions, substitutions, conflict resolutions or snapshot timeouts.

  • Why exclude multidex?

    The reason why we've excluded multidex from getting forced to our required version is that,the dependency name for multidex also contains com.android.support, which is com.android.support:multidex:someVersion where someVersion isn't the same as the support lib version, it's independent from it and that's the reason we're excluding it from being forced to the support lib verison. Note : If you've more such dependencies, you should add them in the if condition above.

and after we've insured that the dependency is indeed a support library ,then we're simply telling gradle to use our desired version for it.

Ashish Ranjan
  • 5,523
  • 2
  • 18
  • 39
  • Well that appeared to work in that adding that to the end of my `build.gradle` didn't break anything (how do I confirm that the file I edited was the 'root' build.gradle?) However, the AS editor still shows the error and when I do a git commit it identifies that error. – Fat Monk Nov 01 '17 at 14:26
  • i meant the project* level `build.gradle` – Ashish Ranjan Nov 01 '17 at 16:38
  • So this goes in the same file as has the `compile` directive under the dependencies? Does the position in the file matter? Should the error (red underline) in the editor (and git) disappear when this is added? – Fat Monk Nov 01 '17 at 16:42
  • OK, have moved that and the error in the editor has gone, but now I get a build time error as follows: `Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'. > com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex`. – Fat Monk Nov 01 '17 at 17:32
  • try cleaning and rebuilding, more details : https://stackoverflow.com/questions/46267621/unable-to-merge-dex – Ashish Ranjan Nov 01 '17 at 17:54
  • 1
    Perfect - no errors on build, no errors in editor. A quicker fix than I expected and app seems to run and function fine - just need to test across API versions again now. – Fat Monk Nov 01 '17 at 18:29
  • Is there any chance you could add an explanation to that code? With my limited knowledge I'm guessing that if it finds a 'dependency' 'conflict' in any 'sub-project configuration' (what is the definition of a sub-project?) then it will 'resolve' the conflict by processing anything that matches 'com.android.support' and does not match 'multidex' (I've seem multidex mentioned in ProGuard, but what does it mean here?) and replacing the library version with "yourSupportLibVersion". Am I close? – Fat Monk Nov 02 '17 at 09:46
  • @FatMonk glad you asked for it. Great! you almost got it, look at the updated answer for detailed explanation. Let me know if I missed anything. – Ashish Ranjan Nov 02 '17 at 10:29
1

The library you mentioned is using v25.3.1 of the appcompat library and hasn't been updated in last 4 months.

To avoid the support library version conflict, I think you should clone/download the library and include it manually as a module dependency in your project so that you can update the version of the appcompat library and use it without any problem.

  • Clone the git repository into another directory.
  • In Android Studio choose File → Import Module and choose the module directory (the one containing file build.gradle)
  • Then right click in your module app → open module settings → dependencies → add module dependency
Vishal Yadav
  • 3,642
  • 3
  • 25
  • 42
Nabin Bhandari
  • 15,949
  • 6
  • 45
  • 59
  • I like the sound of this approach as it gives me a bit more control over my source code. Could you elaborate a bit on where I would need to put the download (under my project or create a new project for it?), and how do I then make it available to my project? (adding as a library via the compile directive made things seem so easy!) – Fat Monk Nov 01 '17 at 11:27
  • 1
    @FatMonk while this is a good solution when you want to customize a library or you just have a single external library, I'm sure it won't be a good idea to clone every single external library if you've many (say 5) libraries and each one of them uses a different version of support library. – Ashish Ranjan Nov 01 '17 at 12:11