2

I have a jcenter library ToggleButtons I develop that I import into my app. After switching to support 26.1.0 in my app, I receive this error:

All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 26.1.0, 25.3.1

ToggleButtons:

com.android.support:cardview-v7:25.3.1

Main app:

com.android.support:design:26.1.0

I'm using other libraries such as Glide that reference even earlier versions of the support library (I haven't upgraded to 4 yet), but those don't have an issue. Have I designed the library improperly somehow?

Anthony
  • 7,638
  • 3
  • 38
  • 71

2 Answers2

1

This was always a recommendation, now they're making it generate errors.

You absolutely can't run an app with both versions, because that would cause duplicated classes errors. That means you must pick one of those manually now, while previously gradle would automatically choose one for you.

I'd suggest you use the higher number, since doing the opposite risks missing new features/assets that either library or app really depends on.

You can add this between your android and dependencies blocks in your application / library module's build.gradle for each conflict you must manually solve:

def supportLibraryVersion = '26.0.1'


configurations.all {
    resolutionStrategy {
        force "com.android.support:cardview-v7:$supportLibraryVersion"
    }
}

I guess you get the idea of how it works.

Edit: As noted by @eugen-pechanec the best practice is having all your support libraries with same version throughout all your projects modules. Also, it's best to use the same numbers on build tools (in module's build.gradle, inside android block).

Fabio
  • 2,654
  • 16
  • 31
  • Except this will only force the cardview-v7 library to a specific version. You'll be using different versions of different support libraries and that's definitely not something you want. Read this https://stackoverflow.com/questions/42949974/android-support-repo-46-0-0-with-android-studio-2-3/42957234#42957234 – Eugen Pechanec Sep 29 '17 at 05:39
  • exactly, it means that for each remaining conflict you add an extra line there to solve it. Also it's good practice to apply the same version to all support library dependencies. – Fabio Sep 29 '17 at 05:40
  • I imported the source for the library and updated to 26 and that did fix the issue. – Anthony Sep 29 '17 at 22:22
  • @EugenPechanec I tried your solution earlier and got an error, but that was because I put it in the project-level build.gradle. It feels like something that would go there. Maybe you could both note that in bold? I still don't understand why Glide doesn't throw this error when they're using support 25._._ – Anthony Sep 29 '17 at 22:22
  • @Anthony, I took another look at your question and maybe found a better fitting answer. Fabio, take a look as well, it may be useful – Eugen Pechanec Sep 30 '17 at 07:40
  • @Fabio `it's best to use the same numbers on build tools` No, no, no, build tools have independent release cycle of support libraries. The r̶u̶l̶e̶ advice is *always use the latest build tools* (now 26.x.x) even if your compile SDK is lower. The only rule is that compile SDK version must match support library version. – Eugen Pechanec Sep 30 '17 at 07:42
1

Here's what your app depends on:

+ design:26.1.0
  + appcompat-v7:26.1.0
    + support-v4:26.1.0
  + recyclerview-v7:26.1.0
    + support-v4:26.1.0

Here's what the library depends on:

+ cardview-v7:25.3.1 (i.e. at least 25.3.1)

Here's what it means:

  1. Card view library doesn't have any (runtime) dependency on other support libraries so technically in this case it's safe to use different versions. However this may change at any time.
  2. More importantly your own code does not define cardview-v7 as a dependency so there's no way for gradle to know it should pull updated version as well.

The easiest fix then is just defining the dependency in your build.gradle:

def supportLibraryVersion = '26.0.1'
compile "com.android.support:cardview-v7:$supportLibraryVersion"

No force, nothing special. Upgrading a dependency is not a problem. Only downgrading is.

I still don't understand why Glide doesn't throw this error when they're using support 25.

As hinted above, Glide uses at least support-v4 25.x.x. And because a newer version of support-v4 is already requested by your own module, the dependency gets silently upgraded.

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
  • So what exactly does the Glide team do to define "at least" 25.x.x? In the version I'm using (3.7), They're still using 'compile' and I don't see anything else special in their build file. – Anthony Sep 30 '17 at 14:33
  • They use exactly the same syntax as you do in build.gradle. The default behavior in gradle is "pick the most recent version of all defined". If you defined support-v4:25.3.1 and a library you use 26.1.0, gradle would pick 26.1.0. The latest version of support-v4 in your project was 26.1.0, so it was picked. The latest version of cardview-v7 in your project was 25.3.1, so it was picked. (Actually it's not about build.gradle. The dependencies are defined by the pom.xml file distributed with the library artifact. But that's not important here.) – Eugen Pechanec Sep 30 '17 at 14:39
  • I forgot that cardview was an extension and not part of the base support library. Now your answer makes perfect sense. So since ToggleButtons never exposes anything from CardView would the new "implementation" or "provided" configurations eliminate this issue as cardview would never be transitive? (I can't find much info on 'provided' yet, it seems rather similar to implementation) – Anthony Sep 30 '17 at 14:58
  • `provided` is the old name for `compileOnly`. If the library defined `compileOnly cardview-v7` your project would not pull the transitive dependency BUT you would still have to supply the library or your app would crash at runtime (CardView would not be compiled in the app). /// If the library defined `implementation cardview-v7` your project would pull the dependency, but you wouldn't get completion hints with CardView in the IDE (good). But the problem would persist: you'd still be using different versions of different support libraries (and you would get the same error while compiling). – Eugen Pechanec Sep 30 '17 at 15:04
  • Wit a local build of the library using `implementation "com.android.support:cardview-v7:25.3.1"` I no longer have an issue building. Build configuration obviously isn't my forte, but according to the docs this would make sense as cardview should never make it to the app classpath, it's effectively sandboxed if I understand it correctly. This isn't conclusive as I have a Kotlin incompatibility with 26 as well, so I'll have to step back some Kotlin code to deploy to confirm for certain. – Anthony Sep 30 '17 at 15:18
  • That's curious. So the original error's gone? Can you check the result .apk, there is a meta-data element in manifest stating the support library version. What's in there? – Eugen Pechanec Sep 30 '17 at 15:22
  • There are two instances: `manifest.meta-data: android:name="android.support.VERSION" android:value="25.3.1"` `manifest.application.meta-data: android:name="android.support.VERSION" android:value="26.1.0"` – Anthony Sep 30 '17 at 16:07
  • So we see that while the compile time error is gone, two different versions still made it into the application. (Irrelevant: Meta tags belong to application element so support library 25.3.1 defined that incorrectly. It should conflict at compile time, which should prompt the consumer to fix their dependencies.) – Eugen Pechanec Sep 30 '17 at 16:15