Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Have a product flavor be a child of another

Tags:

android

gradle

I'm setting up the product flavors in my app and have run into one problem. Two of my product flavors are very similar to each other and only differ by a few resources, let's call them FlavorA and FlavorB. I would like to set it up so that FlavorA is the parent of FlavorB, that way FlavorB can just override a few resources of FlavorA, and then FlavorA overrides a bunch of resources from main. Is there a way to set up a flavor hierarchy such as this? Right now I need to duplicate lots of resources between the two in order for it to work and I would like to eliminate that duplication.

edit: OK. I've had a couple answers so far (both deleted) that were not related to my question so let me clarify. This does not have to do with Java OOP, I already know that quite well. :)

The issue I'm having is that I have a free/paid version of my app, and then several white labels that only include theme changes. The paid version only changes a few assets from the free version (apart from code changes). This is what my productFlavors look like:

productFlavors {
        whiteLabelA {
            applicationId "com.whiteLabelA.android"
        }

        whiteLabelB {
            applicationId "com.whiteLabelB.android"
        }

        mainFree {
            applicationId "com.mainFree.android"
        }

        mainPaid {
            applicationId "com.mainFree.android.paid"
        }
    }

I would like mainPaid to override mainFree since it only changes a few resources. I would like to do it this way rather than a free/paid build type because the white labels don't have paid versions, and it would be easier to have a flavor hierarchy like:

mainPaid extends mainFree {
    applicationId "com.mainFree.android.paid"
}
like image 820
telkins Avatar asked Jul 29 '14 18:07

telkins


2 Answers

I found two solutions:

1. Use flavor dimensions.

android {
  ...
  flavorDimensions 'palette', 'color'

  productFlavors {
    blackAndWhite {
      dimension 'palette'
    }
    redAndWhite {
      dimension 'palette'
    }
    red {
      dimension 'color'
    }
    white {
      dimension 'color'
    }
  }
  variantFilter { variant ->
    def first = variant.getFlavors().get(0).name
    def second = variant.getFlavors().get(1).name
    if(!(first.equals('blackAndWhite') && second.equals('white')) ||
       !(first.equals('redAndWhite') && (second.equals('white') || second.equals('red')))) {
       variant.setIgnore(true);
    }
  }
  ...
}

Because of variantFilter we have 3 combinations instead of 4:

blackAndWhite => white

redAndWhite   => white
              => red

You can consider that as red extending redAndWhite and white extending blackAndWhite or redAndWhite.

This answer and variant filter documentation were helpful.

2. Edit source set.

productFlavors{
    flavor1 {
    }
    flavor2 {
    }
}

sourceSets {
    flavor2 {
        java.srcDirs = sourceSets.flavor1.java.srcDirs
        res.srcDirs = sourceSets.flavor1.res.srcDirs
        resources.srcDirs = sourceSets.flavor1.resources.srcDirs
        aidl.srcDirs = sourceSets.flavor1.aidl.srcDirs
        renderscript.srcDirs = sourceSets.flavor1.renderscript.srcDirs
        assets.srcDirs = sourceSets.flavor1.assets.srcDirs
    }
}

Code example was shamelessly copied from this blog post. Big thanks to its author.

like image 69
mixel Avatar answered Oct 09 '22 02:10

mixel


I was looking for a similar thing in gradle and found Multi-flavor variants. I have an app that should have versions A and B, and each version has dev and pro environments, so I ended up with this in my gradle:

flavorDimensions 'app', 'environment'

productFlavors {
    versionA {
        flavorDimension 'app'
    }
    versionB {
        flavorDimension 'app'
    }
    pre {
        flavorDimension 'environment'
    }
    pro {
        flavorDimension 'environment'
    }
}

And in my build variants I have versionAPreDebug, versionAPreRelease, versionBPreDebug, versionBPreRelease, etc. I think what you need is something like that.

like image 25
allo86 Avatar answered Oct 09 '22 03:10

allo86