Question

I have a base android project that gets tweaked and would like to generate different APKs. Typically the changes are help links, icons/images, hiding certain functions etc.

In iOS (Xcode) and in Win store app (VS 2012 exp), it is possible to create multiple targets to control the resources bundled with the target as well us programmatically change behavior using the C flags.

Is it possible to do the same for an android project using eclipse ADT? The main issue I see is that, each APK changes the bundle signature (like com.xxx.yyy) and since every file has that package com.xxx.yyy in the files, it is not possible to use that file in a different project (which has a signature like comm.aaa.bbb).

Was it helpful?

Solution

In eclipse .apk builds with Ant and don't support multiple APKs build. Of course you can write your own script, but it will be difficult.

Fortunately, there is another build system, which is called Gradle and it's supported by android developers. http://tools.android.com/tech-docs/new-build-system/user-guide

You are interested in a section called "Build Variants"

But not everything is so simple, Eclipse with ADT and Gradle are not compatible but Android Studio yes.

OTHER TIPS

The source of this problem is Java itself, where you can't have things similar to #ifdef and most compiler don't allow completely replacing a class or part of it either.

I actually have a base project from which I build 6 APKs already, and more soon.

Each APK uses its own package name, however the whole code is under a single package, but that doesn't create any issue.

There's however many issues: - All resources, all classes will be in the target APKs, whether used or not. - Different behavior means different code or different resources, each of which must be handled differently.

For resources, it's "quite easy", just make replacement resources in the final application projects. However unused resources will be left over.

For classes, that's where it becomes very complicated.

  • To create slightly different behavior you can use reflection and interfaces, each APK implementing it's own version of the interface using a common name eg myActivityPrj which is retrieved using reflection.

  • Sometimes it's also easier to test the APK package name from within the code, so in the Application object, I set some boolean as to which APK is actually running. Making sure to use those only from the UI to avoid any performance hit.

  • To create very different behavior, for example an activity is not used in an APK, well, could use above method and a flag saying available or not, but what a waste of space inside the APK!

  • Another option is to break-down the central project in smaller pieces, if at all possible!

To actually make APK smaller, I found only one way so far: create a Java project which will copy the central project and then remove and/or replace files within this copy, from a remote source tree (a directory named "replacement-files" which contains a res and src folder).

For resources, that java project will actually parse all strings.xml and remove unused strings from a hard-coded list, can't trust lint output as some resources are used in sub-projects and lint doesn't care.

So far, the APK that includes all features is about 10MB, one variation is about 4MB, whereas it should actually be less than 2MB. Another variation is about 8MB, whereas it should really be 2 or 3MB. The above method is overly complicated and being able to removed unused code and resources is getting more and more complicated.

I've looked at various other solutions, but they're all very complicated with a lot of restrictions, constraints.

After 4 years of development on Android, my only conclusion is that Java is the poorest choice possible for a mobile device: slow, inefficient, resource hungry, and very inflexible. Looking at the NDK, it appears very inconvenient and very limited.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top