Android: Using Gradle
On a couple of Android projects I'm working on, I've switched to using the new Gradle Build system. The idea of storing the entire build configuration in one place is great.
My early experience of Gradle seemed to cause more problems than it solved. However, this was probably due to lack of understanding as much as the early status of the tools. As well as taking the time to learn more about Gradle, recent releases of the toolkit also seem far more stable and integrated with the Android Studio/IDEA IDE.
This post is a summary of how I've solved various tasks with Gradle and what I've learned so far. Hopefully it will help guide you if you're getting started with Gradle, and serve as a handy reminder. These instructions are based on using Android Studio 0.4:
Including an external Jar
- Create a
libs
folder under your project's top-level folder. - Copy the
.jar
file into the newlibs
folder, or a sub-folder. - In your app's
build.gradle
, add thejar
as a file dependency:
// /MyProject/my-app/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.8.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
flatDir {
dirs 'libs'
}
}
android {
// ...
}
dependencies {
compile files('libs/somelibrary.jar')
}
Including an external library module
- Add a new module at the top level of your project (e.g.
MyProject/my-library
) - Inside your project's
settings.gradle
, create a reference to the module. The reference is a path to your module relative to the Project root. Note that you use:
as a path seperator rather than/
:
// MyProject/settings.gradle
include ':my-library'
- In your app's
build.gradle
, add the external library as a project dependency:
// /MyProject/MyApp/build.gradle
android {
// ...
}
dependencies {
compile project(':my-library')
}
Including Google Play Services
Google Play Services is increasingly becoming the only way to interact with Google's APIs (this is a good thing, as it will hopefully help to reduce platform fragmentation). The Google Play Services are now provided through a local repository.
- Ensure that the Google Play Services repository is added in the Android SDK Manager:2. Add the dependencies to your
build.gradle
file corresponding to the services you want to use:
// /MyProject/MyApp/build.gradle
android {
// ...
}
dependencies {
compile 'com.google.android.gms:play-services:3.2.+'
}
The same is also true of the Android Support Libraries which are provided through a separate local repository:
// /MyProject/MyApp/build.gradle
dependencies {
compile 'com.android.support:support-v4:19.0.0'
compile 'com.android.support:gridlayout-v7:19.0.0'
compile 'com.android.support:appcompat-v7:19.0.0'
// ...
}
Product Flavours and Build Types
In all the documentation, I couldn't find a explanation of the difference between a product flavour and a build type.
Put simply, a product flavour is a different edition your app that you might release on Google Play, the most common example being a free and paid edition of your app. I've not really used these much, but one thing you can do is configure a different package name for your app depending on which flavour you use, e.g:
When the app is compiled, it will use the appropriate package name according to the product flavour your have built.
A build type is an environment setting for your app. By default, a debug (development) and release (production) build type are set up. I usually add a third staging build type.
Build types let you set environment. Specific values using the build config object. This is great for setting things like ContentProvider
authorities and API endpoints:
// /MyProject/MyApp/build.gradle
android {
buildTypes {
debug {
buildConfigField "String", "PROVIDER_AUTHORITY", "\"com.example.app.debug.provider\""
buildConfigField "String", "API_ENDPOINT", "\"http://development.localhost/\""
}
staging {
buildConfigField "String", "PROVIDER_AUTHORITY", "\"com.example.app.beta.provider\""
buildConfigField "String", "API_ENDPOINT", "\"http://beta.example.com/api/\""
}
release {
buildConfigField "String", "PROVIDER_AUTHORITY", "\"com.example.app.provider\""
buildConfigField "String", "API_ENDPOINT", "\"http://api.example.com/api/\""
}
}
}
With product flavours and build types, you could generate a debugFree
apk of your app for testing, and a releasePaid
apk for distribution on the Play Store.
Keeping release signing configuration out of source control
The keystore and passwords for signing your release jars is now also configured through the Gradle build script. Like any sensitive data, though, you should ensure this is never published to your code repository.
Instead, using the code from this gist lets you keep your signing data in an external file which Gradle loads at compile time. I add a signing.properties.example
file to my repository to server as a reminder to set the correct values:
// /MyProject/MyApp/build.gradle
android {
// ...
}
dependencies {
// ...
}
def Properties props = new Properties()
def propFile = new File('signing.properties')
if (propFile.canRead()) {
props.load(new FileInputStream(propFile))
if (props != null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {
android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
} else {
println 'signing.properties found but some entries are missing'
android.buildTypes.release.signingConfig = null
}
} else {
println 'signing.properties not found'
android.buildTypes.release.signingConfig = null
}
# signing.properties.example
STORE_FILE=/path/to/your.keystore
STORE_PASSWORD=yourkeystorepass
KEY_ALIAS=projectkeyalias
KEY_PASSWORD=keyaliaspassword
👋 Thanks for reading - I hope you enjoyed this post. If you find it helpful and want to support further writing and tutorials like this one, please consider supporting my work with a coffee!
Support ☕️