To start, let's touch on using resource values in an application. If you append a quantifying value such as -xxhdpi, -land or -sw600dp to a resource folder, then the resource values in those folders will override the values in their main counterpart folder for devices that fit the appended values criteria. This means that if a device is in landscape mode, it will use resources from values-land over those in values if available, and if the device is at least a small tablet, then items in values-sw600dp will take precedence.
The differences here can be seen in the following example screen shot, where one line of text is changed depending on the default value (for portrait devices) and the values-land string value. Without any code changes, the device will choose which string value to use based on the orientation of the phone.
default orientation string - portrait |
landscape orientation string on a Nexus 4 |
Now that we have a base understanding of resource hierarchies in the Android framework, let's move on to the overall goal of this tutorial - reskinning an app using product flavors. This is done almost entirely in the build.gradle file, though there will be some additions in the project folder structure. A default Android application in Android Studio will already come with the build type node populated for debug and release.
buildTypes {
release {
//This is where the signing cert would be referenced for the release build
}
debug {
//This is where the signing cert would be referenced for the debug build
}
}
Under the buildTypes node, we can define the main categories of product flavors that we will want to use. When generating a project, one type of each of these flavors will be used, as well as one of the build types.
flavorDimensions "color", "number"
Once the types of flavor dimensions are defined, we can start declaring types of product flavors and assigning them to a flavor dimension.
productFlavors {
blue {
applicationId "com.ptrprograms.gradleproductflavorsblue"
flavorDimension "color"
}
green {
applicationId "com.ptrprograms.gradleproductflavorsgreen"
flavorDimension "color"
}
orange {
applicationId "com.ptrprograms.gradleproductflavorsorange"
flavorDimension "color"
}
purple {
applicationId "com.ptrprograms.gradleproductflavorspurple"
flavorDimension "color"
}
red {
applicationId "com.ptrprograms.gradleproductflavorsred"
flavorDimension "color"
}
yellow {
applicationId "com.ptrprograms.gradleproductflavorsyellow"
flavorDimension "color"
}
one {
flavorDimension "number"
}
two {
flavorDimension "number"
}
}
Note that each of the color flavors has an applicationId value set. This allows us to differentiate between our products, getting multiple reskinned applications onto the Play Store with the same code base. With the product flavors defined, we can now use the Build Variants window in Android Studio to pick a mix of build types and product flavors to install or build.
With these values filled out, we can quickly generate similar apps with cosmetic changes, as can be seen from the blue version of the app at the beginning of this post and this green product running on a Nexus 7.
And with that we are able to generate many different applications using a similar code base with different values per product for colors, images, text and any other available type of resource, so that multiple apps can be built quickly with just some planning and organization.