Multiple Android Application Package .apk files from single source code
Asked Answered
S

10

49

I would like an Android build system procedure, command line or Eclipse, to generate several .apk files from a single source codebase. Some common reasons for this - having specific versions for markets with different requirements or a free and paid version.

This question IS NOT ABOUT:

Google says "you probably need to create separate Android projects for each APK you intend to publish so that you can appropriately develop them separately. You can do this by simply duplicating your existing project and give it a new name." Then they kindly suggest using libraries, which I understand. Then, they mention in passing exactly what I do want: "a build system that can output different resources based on the build configuration"

  • I know that to accomplish conditional compilation in JAVA one can key off a 'public static final' variable. There is an example of tweaking such a value in build.xml. Any more complete example of an Android Ant build configuration for this or a link to an OSS project doing that now, please? BTW, build.xml is auto-generated, but I have seen people hacking it, so how does that work?

  • With the package name declared in Manifest.xml as package="com.example.appname", if one needs to emit multiple .apks that vary that name, is one stuck with a separate project for each?

Sandstorm answered 21/9, 2011 at 23:6 Comment(1)
The better answer to this is to use Gradle (see my answer below), officially supported by Android Studio. Much more dynamic (additional apps can easily be added at will). There is no variable specifying which app is being coded for, and there's only one main activity and one AndroidManifest, as it should be.Silurid
S
12

I'm generating 2 different APK's (demo and production) from one single source tree with 3 small modifications:

1) I have public static final DEMO=true; //false; in my Application class and depending on that value I used to switch code between demo/production features

2) There are 2 main activities, like:

package mypackage;
public class MyProduction extends Activity 
{
    //blah-blah
}

package mypackage.demo;
public class MyDemoActivity extends mypackage.MyProductionActivity
{
    //blah-blah
}

3) And in the end 2 separate AndroidManifest.xml files which points to different launcher activities depending on demo/production switch

I'm switching between 2 APK's manually, but see nothing difficult in writing small ANT task to switch between them automatically

Slacks answered 5/10, 2011 at 16:24 Comment(7)
A combination of two Manifest files with two activities defined, great.Sandstorm
@WalterKarshat I know, I'm great :), though it was real pain to invent wheelSlacks
This seems like a good approach. If I understand your approach correctly, then you have a typo; you probably meant to call the class MyProduction MyProductionActivity, so that it would match with the class from which MyDemoActivity is inheriting.Cari
Also, the article referenced in the answer by Emmanuel seems to be saying that changing the manifest package will cause R.java to be automatically generated in the new (e.g., demo) package, throwing off all your existing imports for resources. Did you encounter that? If so, how was it addressed?Cari
Question: Might it be possible to just change the package name in the manifest element, and then just give a full path for each Activity in the manifest, without creating a new Activity for the demo at all (relying instead on the DEMO=true variable)? That seems to be the approach taken in the article referenced by Emmanuel's answer. I am just learning this stuff myself, and only wanted to point out issues that seem to be raised by the aforementioned article.Cari
While this answer was probably correct in 2011, it is now very out of date. A better answer would be to use gradle product flavors as answered by @Silurid below.Funnel
@Funnel u're right - in Gradle now it's very easy to generate several APK's on the same source tree.Slacks
P
11

One way to do it would be to maintain two separate AndroidManifest.xml, one for each configuration. You can switch back and forth between the two either manually (copying) or automatically (build script).

[edit] This person here has a system to do this kind of thing: http://blog.elsdoerfer.name/2010/04/29/android-build-multiple-versions-of-a-project/

Phio answered 3/10, 2011 at 13:48 Comment(4)
That's a useful hint, thanks. Any example of how to do that in the build script, please?Sandstorm
@Walter Karshat: I added a link to my answer. I hope this is what you need.Phio
Thanks for the follow-up, this is very much relevant information.Sandstorm
@Walter Karshat: I'm glad you like it. Don't forget to put the little green check mark in the right place! ;-)Phio
S
6

The answer to this screams Gradle, as explained on this website. It's officially built into Android Studio and is encouraged.

It's amazing; I've built 3 separate apps using the same source code, with customized text and graphics, with no special coding whatsoever. Just some directory and Gradle setup is required, and other posts of mine can be found with answers to both.

It seems to explain all the basics really well. For the answer to your specific question, look for the section Product Flavors under Build Variants, where it describes specifying different flavors.

As the website explains, part of the purpose behind this design was to make it more dynamic and more easily allow multiple APKs to be created with essentially the same code, which sounds exactly like what you're doing.

I probably didn't explain it the best, but that website does a pretty good job.

Silurid answered 21/4, 2014 at 16:2 Comment(3)
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post.Engineman
I edited it to include the link I meant to include before, which provides the user with an answer.Silurid
Now it looks better, the close vote will probably be ignored by the reviewer, thanks for the improvement.Engineman
G
4

Despite your insistence that this is not about packaging shared code into Android libraries, it sort of is. You've stated that markets may have different requirements or having a free and a paid version. In each of these examples, your two final output APKs have different behavior and/or resources. You can put the vast majority of your code in a shared Android library, and then maintain the differences in your actual projects.

For example, I've worked on apps where they need to be released both to the Android Market and the Amazon AppStore. The Amazon AppStore requires that if you link to a market page for the app, it must be Amazon's (as opposed to the Android Market page). You can store a URL in a resource in the library and use that in your code, but then override that resource in the Amazon project to point to the appropriate Amazon URL.

If you structure it right, you can do similar things in code because your starting point is your Application object which you can subclass and do different things with.

That said, if you want to add an Ant step that changes the package name in the manifest, it is just XML. It shouldn't be hard to modify as a precompilation step.

Glynis answered 21/9, 2011 at 23:25 Comment(3)
+1 for use android libraries for this use case. It is what you want.Lait
I am sold on Software Engineering benefits of pushing code common between two projects into a library, Android or otherwise.Sandstorm
Library suggestion is orthogonal to the fact that I'd rather maintain a single Android project and have a way to generate multiple binary targets. Google explicitly talks about generating multiple .apk files for the same package, which differ in SDK and GL version and screen size support, but then give no further guidance. I'd like to hear from people who implemented such a setup already or can point to projects that did.Sandstorm
F
3

This article has a good walk-through with examples of how to amend config files at build time; see in particular the Customizing the build and Using a Java configuration file sections. Note that some of the information about build.xml and ant is a little bit out-of-date now.

Foulmouthed answered 4/10, 2011 at 15:31 Comment(1)
Seems to me that the complete solution would involve both messing with the Manifest file to control included resources and package names and also with the build system to compile Java conditionally and perhaps to emit several .apk files. Thanks for the link!Sandstorm
P
2

Here's our situation: we have a single codebase from which we release for several clients. Each of them has various requirements regarding titles, backgrounds and other resources in the application (let alone package names).

Build is handled by a Ruby script that modifies AndroidManifest, copies/replaces certain resources from client-specific folders and then moves on to Android's standart build routine. After the build is done, script resets changed files back to their original, 'default' state.

Well... Maybe it's not optimal and definitely not Android-specific, but that's how we do it.

Pacify answered 4/10, 2011 at 7:41 Comment(5)
Changing files in-place and than changing them back is a tad too 'magic' for me, but I'm glad that it works out in your installation.Sandstorm
I would worry about dependencies between the source and the Ruby script.Cari
There are no dependencies, the script does not modify source code, only resources.Pacify
So every application built has the same package name?Neapolitan
Android and Java packages are pretty much independent. Full activity name in this case looks something like this: vendor.specific.package/com.company.product.MainActivityPacify
W
2

I had the same problem but packing all in one project with flags is no solution for me. I wrote an example how to do that with Maven:

How to create multiple Android apk files from one codebase organized by a Maven multi module project.

Wane answered 14/4, 2013 at 13:33 Comment(2)
Solid solution, very well documented in the linked blog post. Thanks, Bevor!Sandstorm
Should update this link to: blog.zonacroft.com/blog/2013/04/14/…Gravy
P
1

My team build 2 different build using single code base + additional code. As android build is based on ant script, I use ant script to do this work.

I used xmltask to manipulate manifest xml file and many ant task ( regexp , copy..) to edit source code.

I prepared template project template ( including build.xml , default.properties, local.properties) and copied new source code into those project templates. when copy completed, run build.xml parallel to shorten build time. when build finished, I get multiple apk files.

Panettone answered 6/10, 2011 at 15:19 Comment(0)
A
1

It's easily to achieve your goal by using Android Studio build variants which use graddle as the build system.

Check here for more detailed information.

Anaanabaena answered 20/12, 2014 at 16:25 Comment(2)
I have to agree with alijandro, in that above information has to do with the state of Android build environment four years ago. It all has changedSandstorm
Please organized your answer in more detailed and easy to understandQuod
D
0

I think that the best way remain to use libray for common sources and two different Android project for demo and production package. This because in Java it is very simple to make a reverse engeneering from apk to sources. If you use the same sources for demo and production, someone could hacking your apk downloading the demo package, extracting the java sources and unlock the sources changing the variable to use it as production version. With library you can preserve part of sources in the production package, in this way there is no way to use demo package as production package.

Debbi answered 16/4, 2013 at 21:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.