Common tips about Gradle

If you are using Gradle, you already know many of these tips.

In the last days many devs (they are using Eclipse) asked me some questions about Gradle.

I will not talk about what is Gradle, because you can find very good tutorial about it.
I will collect some common (and basic) cases.

First of all, if you are looking for a good tutorial, I suggest you these links:
Android Studio IDE helps you to manage Gradle files, but I suggest you understand what are the gradle files, so you can easily edit them manually.

I've just created a new project
It is important to understand the gradle structure.
- root
  - myProject
     build.gradle
  setting.gradle
  build.gradle
At the root project you will find 2 files:
  • settings.gradle
  • build.gradle
settings.gradle tells Gradle at build time that there are sub-projects to build.
Here an example:
  include ':myPproject'
build.gradle defines how to build the project/module.

Why do I find 2 build.gradle files?
Each module has a own build.gradle file.
Also, at the root you will find a top-level build file. It means that is common for all sub-projects/modules (we will see later)

How can I add a library (or a module) to my project?
You can use the IDE, of course. If you want to edit manually the files you can do it:
You can create this folder structure:
- root
  - libfolder
    -- lib1
    -- lib2
  - myProject
     build.gradle
  setting.gradle
  build.gradle
Then you can modify your settings.gradle
  include ':myPproject' , ':libfolder:lib1' , ':libfolder:lib2'
The order of these is unimportant.
Then you have to put a build.gradle in each module. Pay attention: in each module, not in each folder!
- root
  - libfolder
    -- lib1
        build.gradle
    -- lib2
        build.gradle
  - myProject
     build.gradle   
  setting.gradle
  build.gradle
At this point you can config your build.gradle files.
lib1/build.gradle
  //...
  apply plugin: 'android-library'
  //...
lib2/build.gradle
  //...
  apply plugin: 'android-library'
  //...
myProject/build.gradle
  //...
  apply plugin: 'android'
  //...
  dependencies {
    // Libraries
    compile project(':libfolder:lib1')
    compile project(':libfolder:lib2')
  }
Finally Sync your project with gradle file (there is a button in toolbar).

How can I do to have a library (or a module) and 2 projects (or apk) ?
As always we start with the structure.
- root
  - demo
    -- demo1
        build.gradle
    -- demo2
        build.gradle
  - library
     build.gradle   
  setting.gradle
  build.gradle

Then you can modify your settings.gradle
  include ':library' , ':demo:demo1' , ':demo:demo2'
At this point you can config your build.gradle files.
library/build.gradle
  //...
  apply plugin: 'android-library'
  //...
demo1/build.gradle
  //...
  apply plugin: 'android'
  //...
  dependencies {
    // Libraries
    compile project(':library')  
  }

demo2/build.gradle
  //...
  apply plugin: 'android'
  //...
  dependencies {
    // Libraries
    compile project(':library')  
  }
How can I use top level build.gradle

Here you can put the common part for all sub-projects/module. An example?
buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.6.+'
    }
}
allprojects {
    version = VERSION_NAME
    group = GROUP 
}
What does it mean classpath 'com.android.tools.build:gradle:0.6.+' ?
This line makes the Android-Gradle-plugin available to this build.
If you want to use the same version for all module/sub-projects you can use the top-level build.gradle, so it is very easy to change this value.

How do I know which is the latest version?
You can find it in Central Maven.
Go to http://search.maven.org/, search for com.android.tools.build and you will obtain:

Otherwise you can find it in http://gradleplease.appspot.com/.

How can I use support library?
Just add to your build.gradle script this dependency:
    // Support Libraries
    compile 'com.android.support:support-v4:18.0.0'
How can I use action-bar-compat?
    // Action bar compat
    compile 'com.android.support:appcompat-v7:18.0.0'
How can I use actionbarsherlock?
Use http://gradleplease.appspot.com/ to know the last release then:
    // Action bar sherlock
    compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
Can I use the support-library.jar?
Yes you can, but I suggest you not use this!!
With this structure:
- root
  - libfolder
    -- lib1
        libs
          android-support-v4.jar
        build.gradle
In build.gradle:
    dependencies {
       compile files('libs/android-support-v4.jar')
    }
Why is it not recommended?
You can read this doc: http://blog.stylingandroid.com/archives/1904

Is the last support-library-v4 in central maven?
No.
In Android SDK Manager we can find 2 local repository:
  • Android Support Repository
  • Google Repository
Android Studio provides access to these as if they where installed in a local Maven Repository. Update them to have the last releases.

How can I add a JAR in libs folder?
You can use:
    dependencies {
       compile files('libs/file.jar')
    }
How can I add all JARs in libs folder?
You can use
    dependencies {
       compile fileTree(dir: 'libs' , include: '*.jar')
    }
How can I sign my apk?
You can use this:
android {
    compileSdkVersion 18
    buildToolsVersion "18.1.1"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 18
    }

    signingConfigs {
        release {
            storeFile file("release.keystore")
            storePassword "******"
            keyAlias "******"
            keyPassword "******"
        }
    }

    buildTypes {
        release {
             signingConfig signingConfigs.release
        }
    }
}
I don't want to put my password in build.gradle
You can store your password in a signing.properties file.
  STORE_FILE=/path/to/your.keystore
  STORE_PASSWORD=yourkeystorepass
  KEY_ALIAS=projectkeyalias
  KEY_PASSWORD=keyaliaspassword
android {
    compileSdkVersion 18
    buildToolsVersion "18.1.1"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 18
    }

    signingConfigs {
        release 
    }

    buildTypes {
        release {
             signingConfig signingConfigs.release
        }
    }
}

def Properties props = new Properties()
def propFile = 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')) {

        println 'RELEASE BUILD SIGNING'

        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 'RELEASE BUILD NOT FOUND SIGNING PROPERTIES'

        android.buildTypes.release.signingConfig = null
    }
}else {
    println 'RELEASE BUILD NOT FOUND SIGNING FILE'
    android.buildTypes.release.signingConfig = null
}
Otherwise you can prompt for user input using:
   signingConfigs {
      release {
         storeFile file(System.console().readLine("\n\$ Enter keystore path: "))
         storePassword System.console().readLine("\n\$ Enter keystore password: ")
         keyAlias System.console().readLine("\n\$ Enter key alias: ")
         keyPassword System.console().readLine("\n\$ Enter key password: ")
      }
  }

Does build.gradle override my AndroidManifest?
Yes!
For example, you can define your versionName and versionCode in your build.gradle: android { compileSdkVersion 18 buildToolsVersion "18.1.1" defaultConfig { minSdkVersion 14 targetSdkVersion 18 versionName 1 versionCode 1 } }
Or better you can use gradle.properties file (!)
- root
  - demo
    -- demo1
        build.gradle
    -- demo2
        build.gradle
  - library
     build.gradle   
  gradle.properties
  setting.gradle
  build.gradle
gradle.properties file
  VERSION_NAME=0.6.1-SNAPSHOT
  VERSION_CODE=10
In top level build.gradle you can reference it:
allprojects {
    version = VERSION_NAME
    versionCode = VERSION_CODE
}
In module build.gradle:
android {
    compileSdkVersion 18
    buildToolsVersion "18.1.1"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 18
        versionName project.VERSION_NAME
        versionCode Integer.parseInt(project.VERSION_CODE)
    }
}

Comments

Popular posts from this blog

AntiPattern: freezing a UI with Broadcast Receiver

NotificationListenerService and kitkat

How to centralize the support libraries dependencies in gradle