Since Android moved to Gradle I tought it would be a good idea to renew my post on building an Android app from scratch to use Gradle instead of ant.
The first thing we need to do is to create the folder structure for our project:
1
2
3
4
5
6
7
8
Project/
|---build.gradle
|---src/
|---main/
|---AndroidManifest.xml
|---res
|---java
|---src (Code goes here)
The simplest build.gradle will look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.11.1'
}
}
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
}
If you create a manifest file and some code you should be able to build your project using this command:
1
gradle build
That should be enough to get you started and be able to build an app.
Another thing that is pretty easy to add when using gradle is PMD for code static analysis:
1
2
3
4
5
6
7
// ---------------- Pmd ------------------
apply plugin: 'pmd'
pmd {
ruleSetFiles = files('pmd_rules.xml')
}
The next step is to add tests. I write my tests using Robolectric and place them under Project/tests/unit. The android plugin doesn’t support Robolectric tests by default so I had to add some stuff to my build.gradle file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// ----------- Unit tests ---------------
repositories {
mavenCentral()
}
// extend the runtime
configurations {
unitTestCompile.extendsFrom runtime
unitTestRuntime.extendsFrom unitTestCompile
}
// add to dependencies
dependencies {
unitTestCompile files("$project.buildDir/intermediates/classes/debug")
unitTestCompile files("$project.buildDir/intermediates/res/debug")
unitTestCompile 'org.robolectric:robolectric:2.3'
unitTestCompile 'junit:junit:4.11'
unitTestCompile 'org.mockito:mockito-core:1.9.5'
unitTestCompile 'com.google.android:android:4.0.1.2'
}
// add a new unitTest sourceSet
sourceSets {
unitTest {
java.srcDir file('tests/unit/src')
}
}
// add the unitTest task
task unitTest(type:Test, dependsOn: assemble) {
description = "run unit tests"
testClassesDir = project.sourceSets.unitTest.output.classesDir
classpath = project.sourceSets.unitTest.runtimeClasspath
}
// bind to check
check.dependsOn unitTest
Now I can run my tests using this command:
1
gradle unitTest
The last step of my build is UI Automation. I like Espresso so I had to add it to my dependencies:
1
2
3
dependencies {
androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r3'
}
Then I just placed my tests under src/androidTest/java/src/ and ran them using this command:
1
gradle connectedAndroidTest
At the end my build.gradle file looks something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.1'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'LICENSE.txt'
}
}
dependencies {
compile 'com.google.android.gms:play-services:4.4.52'
androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r3'
}
// ----------- Unit tests ---------------
repositories {
mavenCentral()
}
// extend the runtime
configurations {
unitTestCompile.extendsFrom runtime
unitTestRuntime.extendsFrom unitTestCompile
}
// add to dependencies
dependencies {
unitTestCompile files("$project.buildDir/intermediates/classes/debug")
unitTestCompile files("$project.buildDir/intermediates/res/debug")
unitTestCompile 'org.robolectric:robolectric:2.3'
unitTestCompile 'junit:junit:4.11'
unitTestCompile 'org.mockito:mockito-core:1.9.5'
unitTestCompile 'com.google.android:android:4.0.1.2'
}
// add a new unitTest sourceSet
sourceSets {
unitTest {
java.srcDir file('tests/unit/src')
}
}
// add the unitTest task
task unitTest(type:Test, dependsOn: assemble) {
description = "run unit tests"
testClassesDir = project.sourceSets.unitTest.output.classesDir
classpath = project.sourceSets.unitTest.runtimeClasspath
}
// bind to check
check.dependsOn unitTest
// ---------------- Pmd ------------------
apply plugin: 'pmd'
pmd {
ruleSetFiles = files('pmd_rules.xml')
}
android
automation
java
mobile
productivity
testing
]