Android support library incompatiblity - android

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?

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).

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:
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.
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.

Related

Which com.google.android.gms:play-services-ads version is compatible with com.android.support:appcompat-v7:27.1.1?

No duplicate:
In my question I've already linked an answer similar to the supposed duplicate and explained, why I'm not looking for such an answer.
Android Studio 3.2.1 automatically included
implementation 'com.android.support:appcompat-v7:27.1.1'
for my new app. I manually included
implementation 'com.google.android.gms:play-services-ads:17.1.1'
following the official guide.
The official guide from google seems to be outdated, as Android Studio immediately suggests using version 17.1.3 instead.
In both cases however there is a red line under appcompat-v7 and a tooltip warning me that:
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.
I do get the general problem here, play-services-ads transitively depends on an old version of some support library. This answer suggests to simply include the offending libraries manually in the correct version.
However, I don't like this solution for two reasons:
I simply don't want to deal with problems like this. There should be compatible versions available for the google libraries.
At some point in the future I might have forgotten why I included all these libraries I don't even know what they do. I might want to update the appcompat and play-services-ads dependencies without thinking about all this again.
Is version 17.1.3 the most recent version of play-services-ads as of now? Does that mean that play-services-ads is generally lagging behind? If so, I would prefer to downgrade appcompat-v7 instead of including some library versions manually.
What would be the correct version of appcomat-v7 for play-services-ads version 17.1.3? Or maybe more generally asked: Which are the most recent versions of appcompat-v7 and play-services-ads that work together hassle free?
26.1.0 is the correct appcompat-v7 version for play-services-ads 17.1.*
implementation 'com.android.support:appcompat-v7:26.1.0'
This also requires compileSdkVersion and targetSdkVersion to be set to 26.

Cannot remove an external library causing the variation in library version conflict

I could not get myself out of this situation. It keeps on showing libraries version must be exact same even if there is no conflicting library in "build.gradle". Possibly because of conflicting version in the External Libraries and I can't remove one.
android {
configurations.all {
resolutionStrategy.force 'libraryname:version'
}
}
That will force it to use a specific version of the library no matter what. Note that this can break their library if there are incompatible changes.

How does Gradle choose between more than 1 versions of the same library in a gradle tree?

Let say I have added Facebook and Twitter dependencies in my app.
com.facebook.android:facebook-android-sdk:4.22.1
com.twitter.sdk.android:twitter:2.1.0
When i look at Gradle tree, They come up with bunch of other transitive dependencies.
Now If Facebook uses com.android.support:support-annotations:24.1.1 and twitter uses com.android.support:support-annotations:25.0.3
Then which version gradle will use.
In gradle tree, It shows -> in front of older version of dependency. I learnt that this means gradle will use the newer version, and will not use the older version.
But this can be a problem, because some libraries are meant to run on the specific versions, and i have faced this problem.
In one of article i found out how npm manages these dependencies conflicts, but i am still unsure how gradle will manage between different version of same library.
You can't have different versions of the same library inside an apk.
As you mentioned, by default, Gradle puts the newest one to the build. If you want to specify a concrete version of the library that should be used in your project, you can add a direct compile (or implementation / api for Android Gradle Plugin v3+) statement with a required version to get one.
Also, you can force version using a special syntax, but it can lead to some problems later. You can find more information about version conflicts resolution in this post

Correct way to resolve error: all support libraries must use the exact same version

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.
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).
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.
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).
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)
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.
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

How can I download an old version of the Android support library?

I'm targeting Android 19 (because that's what my phone is running). I want to add a notification with buttons; it seems the right approach is to use appcompat-v7.app.NotificationCompat.
However, when I add appcompat-v7 from the Android Support repository revision 22.2 (via a build.gradle dependency), it includes a file app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/res/values-v21/values-v21.xml that doesn't compile because it assumes the target is 21+.
I tried deleting that file, but it gets regenerated.
There doesn't seem to be a way to exclude a file from the build.
So, I need to get an older version of the support library or repository, that doesn't include 21 stuff.
I guess I could import all the sources directly (and leave out the v21 stuff), rather than thru the dependency? I'm not clear where to start with that.
I can use the SDK manager to get older versions of the SDK, but it only offers the latest version of the support library.
to directly answer your question it's all that one line on gradle:
compile 'com.android.support:appcompat-v7:22.2.0'
That last part is the version you're getting. 22.2.0 on the example above.
and on this link you can check the revisions numbers:
https://developer.android.com/tools/support-library/index.html#revisions
But you have a fundamentally wrong approach to your issue. You don't have to target the API for the device you have with you. You can easily and safely target the latest API, use the latest AppCompat features and bug fixes.
Lint will give you a warning every time you try to use a feature that is not from your minimumApi, regardless of the targetAPI
In your gradle build file change the dependency to be the 19 version (the version of the library should match the sdk you are compiling with):
dependencies {
compile 'com.android.support:appcompat-v7:19.1.+'
...
}
Edit: If v19 of the support lib doesn't have NotificationCompat, then you can't use that unless you compile against a later SDK. You can't include a support library with a higher version than your compiled SDK - that's the issue you are running into.
In this case change:
android {
compileSdkVersion 22
...
}
and leave the dependency set to the 22 version of the appcompat support lib

Categories

Resources