Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build configuration management in Android / Intellij / Jenkins [closed]

This question might be subjective, but I think Stackoverflow is still the best place to ask:

The problem domain is "advanced Android programming". I do not need information how to set up a single Android project, how to use library projects, or how to use ANT to build a normal project.

Assume you got a running App, an ordinary Android project (IDE of choice is IntelliJ, but that should not really matter) build by Jenkins / Ant / Proguard. The result of this build is a final APK you would put in the Play store.

Now imagine you need this App as a free and a paid version. No problem so far, simply put all shared code into a library project, and create two child projects, one with an App.java enabling license checks, the other one e.g. limiting the usage.

Now imagine you want to target Amazon as well, maybe have a press release version, etc. So your code starts to diverge, with still a lot of stuff shared, but certain parts are specific to e.g. the market you target.

In C# there are "conditional compilation statements", like "IF PLAY_STORE ...". Is there anything similar for Java / Android. Also, do they play nice with ANT and the build process.

But I am not limited to conditional compilation. The "one project per market" approach is a different one. I am just trying to get a feeling of how you manage these various "build configurations" in a manner that is sustainable. Meaning it works for 15 projects, targeting 3 markets in 2 flavors (FREE and PAID). I hope you see what I am hinting at. The code is very very similar for all Apps, but with the example above I will have 90 different APKs - with these numbers the "manually commenting in source code only needed by this build, etc" just does not cut it anymore.

So any tips, tools, search words, experiences with these problem domain (e.g. MAVEN, would it help me with any of it, or is ANT + scripts generating build.xml be better). Another example, if I have a "real" Android project for all target markets, this would allow me to do almost anything. But of course, on the downside, if I add a new page in the lowest level (e.g. a imprint page) I would need to go into 90 Manifest.xml to add the page...

Thanks for any help with this, Chris

PS: I will add some links I find regarding this topic at the bottom, if anybody comes across this question while there are no answers, this might be a "first read this" section

http://www.asyncdev.net/2011/02/android-dev-prod-builds/

http://www.slf4j.org/ (related in the "put JAR in to provide IMPL" way)

(The SLF4J is just a nice approach to reduce dependencies and provide configuration during deploy - by simply adding a different JAR. To use something like this might be overkill for your own projects, but it would be one way. E.g. for license write interface and a bit of code like SLF4J, then provide either PressRelease.jar or Productive.jar in Lib folder during build, changing how the app behaves...)

like image 695
Christian Ruppert Avatar asked Jul 22 '13 08:07

Christian Ruppert


1 Answers

This question is somewhat opinion based since in a complex project there are always more than 1 suitable solutions.

Preamble

I will try to explain some principles I used to deploy Linderdaum Puzzle HD. The game has paid and free versions which differs not only in code, but in UI and in game content.

The game is released for two platforms and several stores (which all have different authorization mechanism):

Android:

  1. Google Play (2: free+paid)
  2. AndroidPit (2: free+paid)
  3. SlideMe (1: free)
  4. Samsung store (1: free)

Blackberry OS 10

  1. BlackBerry World (1: paid)

Windows

  1. We use this version for development and testing on a PC (1: paid)

This gives us 8 different distribution packages.

Environment

Our production toolchain is based on git and TeamCity. No special tools (like Maven, Gradle) are used.

Solution

The end-point of our workflow is TeamCity project page where we have all build configurations corresponding to 8 distribution packages plus some additional builds for debugging (i.e. with additional checks and logs). Any package can be built via a web-interface from anywhere in one click.

For every package there is a git branch name (shared by some packages) so the TeamCity knows from where to pull the sources. Currently we have this branches:

  remotes/origin/master
  remotes/origin/release300-blackberry
  remotes/origin/release300-master
  remotes/origin/release300-paid_apps
  remotes/origin/release300-paid_apps_androidpit

Here release300 represents a version of the game. We have many archive branches for these. These are not development or feature branches - they used only to hold the changes for the particular game package. I.e. in paid_apps there is more game content and paid_apps_androidpit contains AndroidPit licensing library.

The development happens in master and in feature branches that are merged back to master. Then a merge process takes place. The directions of merge are (and only these directions):

master -> release300-master -> release300-paid_apps -> release300-paid_apps_androidpit
        \
         \-> release300-blackberry

I.e, release300-paid_apps_androidpit has basically the same content as release300-paid_apps, however, it adds some new features (like licensing library, etc). And release300-blackberry is completely separate since it has to target devices with an unusual screen aspect ratio 1:1 and has a UI of the special design. So, these 5 branches are used to build our 8 distro packs.

We never merge changes from these release branches back to master. The bugfixes are propagated in the same direction.

Every package has its own script file, I.e. build of the free application for Google Play is as simple as calling the Python script BuildAndroid.py on branch release300-master.

The same idea applies for all other packages: use just a single-line TeamCity command line build runner.

like image 158
Sergey K. Avatar answered Sep 26 '22 00:09

Sergey K.