68

I have the two default build types: debug / release and a couple of flavors: prod / dev.

Now I want to exclude the build variant dev-release, but keep all other possible combinations. Is there a way to achieve this?

Kuno
  • 3,492
  • 2
  • 28
  • 44

9 Answers9

134

Variant filter

Use the variantFilter of the gradle android plugin to mark certain combinations as ignored. Here is an example from the official documentation that works with flavor dimensions and shows how it can be used:

android {
  ...
  buildTypes {...}

  flavorDimensions "api", "mode"
  productFlavors {
    demo {...}
    full {...}
    minApi24 {...}
    minApi23 {...}
    minApi21 {...}
  }

  variantFilter { variant ->
      def names = variant.flavors*.name
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
      if (names.contains("minApi21") && names.contains("demo")) {
          // Gradle ignores any variants that satisfy the conditions above.
          setIgnore(true)
      }
  }
}

As the comment says, you can also check the buildType like so:

android {
    variantFilter { variant ->
        def names = variant.flavors*.name
        if(variant.buildType.name == 'release' && names.contains("myforbiddenflavor")) {
            setIgnore(true)
        }
    }
}
ade.se
  • 1,644
  • 1
  • 11
  • 11
  • Can you tell me more about `android.variantFilter { variant ->`, like what type of object is `variant`?, or what params does `variantFilter` function accepts? Could you provide a link where I can find documentation for this? Thanks a lot. – Tony Dinh Feb 01 '15 at 16:15
  • @TrungDQ, have a look at this document, under release 0.9.0: http://tools.android.com/tech-docs/new-build-system – ade.se Feb 02 '15 at 10:55
  • I saw that document before, that looks like a change log, not a full document, I have go around that page but could not find the full detail document anywhere. I wonder if it really exists on the internet. Could you help me with that? I am having a problem with gradle/android and I need the document for reference. – Tony Dinh Feb 03 '15 at 04:06
  • Sorry, I've looked around but I can't seem to find any other documentation on this right now. The best I give you is the commit where it was added: https://android.googlesource.com/platform/tools/base/+/bb739b8f05c937b08fedddd7bf13050f222472d2 – ade.se Feb 03 '15 at 10:26
  • I've added an issue to add some documentation for it to the android team at https://code.google.com/p/android/issues/detail?id=131534 – ade.se Feb 03 '15 at 10:34
  • Thanks a lot for your time. I posted a question about the problem I am dealing with, if you have time please take a look: http://stackoverflow.com/questions/28299376/gradle-android-variantfilter-caused-build-fail-after-upgrade-to-gradle-2-2-1 – Tony Dinh Feb 03 '15 at 12:52
16

Using variant filters like others I found it was easiest to do this by comparing the variant name against a list of variants that I want to keep.

So in my app/build.gradle file I have something like:

android {
    variantFilter { variant ->
        def needed = variant.name in [
                'stagingQuickDebug',       // for development
                'stagingFullDebug',        // for debugging all configurations
                'stagingFullCandidate',    // for local builds before beta release
                'stagingFullRelease',      // for beta releases
                'productionFullCandidate', // for local builds before going public
                'productionFullRelease'    // for public releases
        ]
        variant.setIgnore(!needed)
    }
    buildTypes {
        debug {
        }
        release {
        }
        candidate.initWith(release)
    }
    flavorDimensions "server", "build"
    productFlavors {
        staging {
            dimension "server"
            buildConfigField "String", "API_URL", '"https://example-preprod.com/"'
        }
        production {
            dimension "server"
            buildConfigField "String", "API_URL", '"https://example.com/"'
        }
        quick {
            dimension "build"
            minSdkVersion 21
            resConfigs("en", "xxhdpi")
        }
        full {
            dimension "build"
        }
    }
}
arekolek
  • 9,128
  • 3
  • 58
  • 79
15

When working with flavor dimensions try this one

variantFilter { variant ->
    def dim = variant.flavors.collectEntries {
        [(it.productFlavor.dimension): it.productFlavor.name]
    }

    if (dim.dimensionOne == 'paid' && dim.dimensionSecond == 'someVal') {
        variant.setIgnore(true);
    }
}
Arkadiusz Konior
  • 1,139
  • 13
  • 12
14

If you use flavor dimensions do this:

flavorDimensions "device", "server"

productFlavors {
    emulator {
        dimension = "device"
    }
    phone {
        dimension = "device"
    }
    staging {
        dimension = "server"
    }
    production {
        dimension = "server"
    }
}

android.variantFilter { variant ->
    def device = variant.getFlavors().get(0).name
    def server = variant.getFlavors().get(1).name
    def isRelease = variant.buildType.name.equals('release')
    def isDebug = variant.buildType.name.equals('debug')

    // Disable emulatorProductionRelease build variant
    if (device.equals('emulator') && server.equals('production') && isRelease) {
        variant.setIgnore(true)
    }
}

It's easy to read and you can target specific build variants.

Albert Vila Calvo
  • 15,298
  • 6
  • 62
  • 73
5

The solutions here didn't work for me - I run into this post and added this to build.gradle in my app and it solved the issue for me

gradle.taskGraph.whenReady { graph ->
  graph.allTasks.findAll { it.name ==~ /.*MyVariant.*/ }*.enabled = false
}

This is what it does - waits for gradle to assemble the complete list of tasks to execute and then it marks all the tasks that match the name pattern as disabled

NOTE The match is exact - the expression above lets you match any task that has "MyVariant" somewhere in it's name and it is case sensitive

Noa Drach
  • 2,381
  • 3
  • 26
  • 44
4

One more simpler way

android.variantFilter { variant ->
    if (variant.name == "qaDebug" || variant.name == "devRelease") {
        setIgnore(true)
    }
}

Or if you place this code inside android {} closure, android. can be omitted

android {
    // Please always specify the reason for such filtering
    variantFilter { variant ->
        if (variant.name == "qaDebug" || variant.name == "devRelease") {
            setIgnore(true)
        }
    }
}

Please always put a meaningful comment for things like this.

UPD: For Kotlin Gradle DSL there is another way:

android {
    variantFilter {
        ignore = listOf("qaDebug", "devRelease").contains(name)
    }
}
amatkivskiy
  • 1,154
  • 8
  • 11
3

The answer of @ade.se didn't work for me. But I've struggled a little, and written this, that works great:

android {
compileSdkVersion 22
buildToolsVersion '20.0.0'

variantFilter { variant ->
    if (variant.buildType.name.equals('debug') || variant.buildType.name.equals('release')) {
        variant.setIgnore(true);
    }
}

defaultConfig {
    applicationId "com.fewlaps.quitnow"
    minSdkVersion 15
    targetSdkVersion 22
    versionCode 35
    versionName "1.35"
}

The code you have to add is the variantFilter one, but I've pasted a little of the context to make it easy to understand.

Roc Boronat
  • 11,395
  • 5
  • 47
  • 59
2

See Variant filter answer above.

Old Answer:

It's not possible at the moment, but it's something we want to add. Probably soon.

In the meantime you could disable the assemble task I think. Something like this:

android.applicationVariants.all { variant ->
   if ("devRelease".equals(variant.name)) {
       variant.assembleTask.enabled = false
   }
}
Xavier Ducrohet
  • 28,383
  • 5
  • 88
  • 64
  • Any news on this? The combinations explode quickly, and whenever you run unit tests in Android Studio via the Gradle executor, it first assembles *all* build variants... – mxk Jul 30 '15 at 09:20
  • Use the variant filter explained in the other answer. – Xavier Ducrohet Jul 30 '15 at 22:12
2

In Gradle's Kotlin DSL (i.e. build.gradle.kts), that would be:

variantFilter {
    ignore = buildType.name == "release" &&
             flavors.map { it.name }.contains("dev")
}
Giorgos Kylafas
  • 2,243
  • 25
  • 25