- By default the build system defines two build types,
debug
andrelease
. But in some cases that might not be enough for you, let's "imagine" the situation when you or your team is developing but the backend is behind schedule. You could just hang around or do something else but now you're so excited to continue working on this product that you create a small node.js project or a mock service so that you can continue your development. - This could be the perfect situation to decide to add a build type. So let's add a
mock
build type, so let's say we want to switch between backend depending on the build type, there are serveral ways to do this.
- We can define
BuildConfig
fields, in this case we could define a fieldURI
which we use to make a connection to our backend. This solution is the most straight forward, and is the cleanest code wise because the URI switches based on the build type.
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "URI", "\"http://release.com\""
}
debug {
debuggable true
applicationIdSuffix ".debug"
buildConfigField "String", "URI", "\"http://debug.com\""
}
mock {
applicationIdSuffix ".mock"
buildConfigField "String", "URI", "\"http://localhost:8080\""
}
}
- In order to get the
URI
in code:val URI = BuildConfig.URI
-
Default the build system adds a boolean field for
debug
, which is true only if the build type is debug. You could do this for other types as well. And use it to enable or disable http logging retrofit for example. You don't want this to be enabled in a release version! -
You can do this simply by checking
if(BuildConfig.DEBUG)
Now why would you use this? I could just remove the lines when switching build, or I could just comment the logging real quick. You will forget and unexpected behavior will arise. But even more important, your code is does that for you now. And you can define tests for the different build types!
- So now we could add all the test folders like
app/src/testDemoMock
, within this folder you can write tests that will run from command-line/CI when the build type is MOCK. - To test this we us
./gradlew test
, if you encounter problems while your test run correctly in Android studio try using./gradlew clean test
-
A product flavor is a "flavor" of a product.
-
The most used example is a free or paid app, an admin or user app. Let's take another context: If Coffee is the product. You can have latte and mocha flavors. If we translate this back to development this means: Coffee is our "product" then latte and mocha are two coffee products with a different implementation. I'll illustrate a bit more in depth and in code what that means.
-
Creating product flavors is pretty straight forward. We can do this by adding the following in the app/build.gradle
android {
productFlavors {
demo {
applicationId "be.vergauwen.simon.androidtestingexample.demo"
versionName "1.0-demo"
}
full {
applicationId "be.vergauwen.simon.androidtestingexample.full"
versionName "1.0-full"
}
}
}
-
Since by default a release and debug build type is configured, we now have the following
build variants
- debugDemo
- releaseDemo
- debugFull
- releaseFull
-
We can now define our flavor directories
- app/src/demo
- app/src/testDemo (app/src/androidTestDemo)
- app/src/full
- app/src/testFull (app/src/androidTestFull)
-
Using product flavors, let's say we want a different string to show in our demo and full variant
-
We add the following to
full/res/values/strings.xml
anddemo/res/values/strings.xml
><string name="hello_world">Full version only.</string>
- Ubuntu server (or desktop) running in VirtualBox
- Installed without any additional packages since setting up dns, apache etc is out of scope and depends on your enviroment
- Installing Java with apt-get is easy. First, update the package index:
sudo apt-get update
- Check if Java is not already installed:
java -version
, "The program java can be found in the following packages" means it's not installed - To install JRE execute the following command:
sudo apt-get install default-jre
- To install JDK use
sudo apt-get install default-jdk
wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
tar -xvf android-sdk_r24.4.1-linux.tgz
mv android-sdk-linux /usr/lib/android
rm android-sdk_r24.4.1-linux.tgz
cd /usr/lib/android/tools
sudo apt-get install lib32stdc++6
sudo apt-get install lib32z1
Get some coffee for the next part cause this takes a while!!!!
./android update sdk --no-ui --all
There is a gradle plugin from Jake Wharton (https://github.com/JakeWharton/sdk-manager-plugin) that takes care of missing android dependencies. I don't prefer this setup, cause gradle is not responsible for installing packages on the master server. I will prefer to do this with a cronjob that checks for new packages. * Jenkins now has a option that installs missing android packages if required (not tested yet)
-
This step is not required because you can set Jenkins to use the gradle/wrapper and specify which gradle version you want to use :
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
(Android studio automatically does this for you) -
Because gradle is available trough PPA (Personal Package Archive), we'll first have to add it to our system:
sudo add-apt-repository ppa:cwchien/gradle
-
After we've added it, we'll have to update our repository
sudo apt-get update
-
sudo apt-get install grade
--> If you don't want the latest gradle version you can append a versiongradle-1.5.0
-
IMPORTANT Check which version of gradle is running (!!) to check which Gradle version is required for which android gradle plugin.
gradle -v
, http://tools.android.com/tech-docs/new-build-system/version-compatibility
Gradle recommends NOT using gradle daemon in the CI environment!
- In case you got any of the following errors, you most likely have a mismatch gradle version issue.
Could not find method jcenter() for arguments [] on repository container
> Could not create plugin of type 'AppPlugin'.
sudo apt-get install git
wget --no-check-certificate -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
sudo apt-get update
sudo apt-get upgrade
sudo nano /etc/profile
- add at the end of file:
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export ANDROID_HOME=/usr/lib/android
- Again there are "two approaches" here. One thing is to set everything correctly on your Ubuntu server, and than the Jenkins doesn't need that much configuration anymore. I always make sure everything is set correctly on the Ubuntu server, that way Jenkins will always work also without the additional settings.
- To check/would if your build will succeed you can do this by changing to the Jenkins users
sudo su jenkins
- Once you did this you should be able to use everything so lets do that
git clone https://github.com/username/repo.git
cd repoName
gradle clean assemble
--> if this succeeds the jenkins should be able to successfully build.
- I don't work with any external user system so I let Jenkins maintain it's own user database
- I use matrix-based security Anonymous needs read permission or you won't be able to log in!
More information on how to setup quality assurance for android can be found in my repos.
-
Configuring Static Analysis Collecter Plug-in (Manage Jenkins -> Configure System)