Build configuration management in Android / Intellij / Jenkins

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 eg 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 eg 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 (eg 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 (eg 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. Eg 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...)


You should definitely take a look at

  • Library projects - this will help you with proper code separation and plays well with ant - take a look at our presentation at droidcon here: http://skillsmatter.com/podcast/agile-testing/building-your-app-for-multiple-app-stores)
  • Gradle (aka "new build system") - this will help you with easier build conditions and have slightly better IDE integration (with new Android Studio ) see more information here: http://tools.android.com/tech-docs/new-build-system)
  • UPD: As I see, you're already using LP for you projects. Some tips for making process this easier:

  • Use manifestmerger.enabled=true

  • Take a look at github.com/onepf/OpenIAB


  • 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:

  • Google Play (2: free+paid)
  • AndroidPit (2: free+paid)
  • SlideMe (1: free)
  • Samsung store (1: free)
  • Blackberry OS 10

  • BlackBerry World (1: paid)
  • Windows

  • 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 (ie 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. Ie 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
    

    Ie, 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, Ie 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.


    If you're stuck with ant for reasons you can't control, consider using filters and tokens. You can have .java files generated from templates that correspond to configuration or business logic for each type. Here's an official example:

    <copy file="${build.dir}/version.txt" toFile="${dist.dir}/version.txt">
      <filterset begintoken="%" endtoken="*">
        <filter token="DATE" value="${TODAY}"/>
      </filterset>
    </copy>
    

    This will replace the text @DATE* in ${build.dir}/version.txt with the current date and copy the result to ${dist.dir}/version.txt . This, along with some smart branching, can give you a half-decent preprocessor. The downside is, of course, that it's really slow ( ant in general is, this even more so).

    I really want to be able to recommend Gradle, since it has this functionality built in (product flavors) but unfortunately that's not a serious option while it's under active development. Maybe in a few months but not now.

    链接地址: http://www.djcxy.com/p/14738.html

    上一篇: 狮身人面像:让课堂出现在TOC上

    下一篇: 在Android / Intellij / Jenkins中构建配置管理