Skip to content

Solving Android Gradle Conflicts

Chris Scott edited this page Feb 27, 2018 · 13 revisions

The most common build-issues with Android apps are gradle conflicts between modules specifying different versions of:

  • compileSdkVersion
  • buildToolsVersion
  • Google play-services / firebase version.
  • Google support libraries (ie appcompat-v4, appcompat-v7)

Often the solutions have been to either fork a Github project or use the gradle exclude / force directives:

compile(project(':react-native-device-info')) {
    exclude group: 'com.google.android.gms'  // <-- exclude offending dependency
}
compile ("com.google.android.gms:play-services-gcm:11.8.0") {
    force = true  // <-- force my desired version
}

You'll have a much easier time controlling these conflicts by performing the following technique, as documented in the Android Developer Document Gradle Tips & Tricks (Another good explanation here). More and more, plugin authors are beginning to make their modules aware of application-wide configuration properties, just as this one.

Step 1: 📂 android/build.gradle

In your application's "root" gradle file, define global properties to be used by your app and all the modules you include into it:

buildscript {...}

allprojects {...}

/**
 * Project-wide configuration properties
 */
+ext {
+    compileSdkVersion   = 26
+    targetSdkVersion    = 26
+    buildToolsVersion   = "26.0.2"
+    supportLibVersion   = "26.1.0"
+    googlePlayServicesVersion = "11.8.0"    
+}

Step 2: 📂 android/app/build.gradle

In your app module's build.gradle, implement your new Global Configuration Properties:

android {
+    compileSdkVersion rootProject.compileSdkVersion
+    buildToolsVersion rootProject.buildToolsVersion 

     defaultConfig {
         minSdkVersion 16
+        targetSdkVersion rootProject.targetSdkVersion
        .
        .
        .
     }    
}

dependencies {
+    compile "com.android.support:appcompat-v7:$rootProject.supportLibVersion"
     compile(project(':react-native-device-info'))
     .
     .
     .
}

Example: react-native-device-info

For the example case of react-native-device-info, if you look at its build.gradle, you can see that module is aware of the global configuration property googlePlayServicesVersion.

dependencies {
    def googlePlayServicesVersion = project.hasProperty('googlePlayServicesVersion') ? project.googlePlayServicesVersion : "+"

    compile 'com.facebook.react:react-native:+'
    compile "com.google.android.gms:play-services-gcm:$googlePlayServicesVersion"
}

react-native-device-info is now happily aligned to your own desired version 11.8.0 via your application-wide configuration property googlePlayServicesVersion. Yay, no conflicts!