Workaround for Using Different Versions of Android

2019-05-10 16:44发布

问题:

This is in reference to a warning message appearing in build.gradle file:

All com.android.support libraries must use the exact same version specification (mixing versions may lead to runtime crashes)

I'm well aware of this and use identical versions in my own code / build. However this isn't the case when it comes to some 3rd party libraries that I use.

Sometimes 3rd party libraries use older versions, and some other ones use newer versions - so updating your version of support libraries will not resolve the issue.

There are also scenarios where you may not want to up upgrade versions of support libraries you are using.

Recompiling 3rd party libraries with different versions of support libraries isn't an option either since code isn't not available in my case.

What is the workaround or recommended approach in dealing with this when other referenced 3rd party libraries use different versions of support libraries?

回答1:

You can exclude all of the transitive dependencies or just one by one, then include the desired version in your build.gradle file.

Method 1 - Excluding all dependencies of a lib

Use the transitive field to tell gradle you don't want the transitive dependencies to be resolved. The documentation of transitive says:

Sets whether this dependency should be resolved including or excluding its transitive dependencies. The artifacts belonging to this dependency might themselves have dependencies on other artifacts. The latter are called transitive dependencies.

Example:

compile('com.super.lib:awesome@aar') {
    transitive = false
}

Method 2 - Pick which dependencies you don't want to include

Use the exclude method which:

Adds an exclude rule to exclude transitive dependencies of this dependency.

Example:

compile('com.super.lib:awesome@aar') {
    exclude group: 'com.dont.want.this', module: 'old-artifact'
}

Note, however, that this does not guarantee that the excluded dependency won't be pulled in by another dependency. If you want to exclude a dependency from everywhere, use a configuration-wide exclusion strategy:

configurations.all {
    exclude group: 'com.dont.want.this', module: 'old-artifact'
}

Also, you don't need to specify both group and module names. This example is from the JavaDoc of gradle:

dependencies {
     compile('org.hibernate:hibernate:3.1') {
         //excluding a particular transitive dependency:
         exclude module: 'cglib' //by artifact name
         exclude group: 'org.jmock' //by group
         exclude group: 'org.unwanted', module: 'iAmBuggy' //by both name and group
     }
}

WARNING

Just a friendly reminder about the dangers of changing dependency version numbers.

When you change dependency versions using this technique, you must test the app thoroughly because there can be breaking changes or unexpected behavior in the newer / older versions of the dependencies. It's pretty obvious that a major version number jump will likely result in crashes / unexpected behavior, but you must pay attention even to the patch part of the version number since the lib creator might have expected that the used version of the dependency had some bugs and included some fixes that might break the lib once the bug is fixed.