Building multiple .apk artifacts for different customers with maven - android

i have to setup an android maven build for a customer, which previously was based on ant.
The base app is a white label implementation and the app is distributed to several third party customers. Each of those customer versions uses the same source code and a set of shared resources. But every customer also has some resources specific to their company (constants, assets, etc).
The structure of my android project looks like this. I only included relevant files/folders and the structure is remained from the ant build:
App
|--src
|--res
|--res-customer1
|--res-customer2
|--pom.xml
This means i have to build multiple .apk artifacts from the same source with different resources. What is the best approach to do this?
The first thing i tried was to use different profiles in my main projects pom for every customer. Then i wrote a shell script to execute all maven builds (1 per customer).
Then i came up with using only one release profile in my main project and passing the customer specific properties via command line. Properties are passed via a shell script, similar to my first approach.
But i'm not happy with that, so i thought about using multiple modules. One per customer. But my problem here is, how i can build those from the same source without copying the source from my main project over to all modules?
Or do i have to setup an android project for every customer and refer to my main project as apklib? Will this merge the shared and the customer specific resources?
Is there a best practice to do something like this?
Any other approach is also very welcome.

For only small differences it can be sufficient to just use profiles and a few different properties with resource filter. Profiles however are a bit of a bad pattern in the Maven world and can be hard to work with.
Your hunch to use separate modules for each customer and have the base application be an apklib is correct. I know of several people that have reported on the maven android developers list that this is what they use and works for them. I would personally use that approach in your case as well.
In general I would suggest to ask or at least mention this question on the mailing list.

Related

How to build a mobile app for multiple clients from the same codebase

We have an iOS app and an Android app that we customize for two separate clients. And it's too cumbersome to edit the code when we build for a client.
Is there a way to automate this so that we can just keep maintaining the common codebase and have the client-specific ones in different files? The customizations are quite trivial (e.g. name of the app, backend server address, some strings, etc.)
I'm a web dev not a mobile dev. In Python/Django, I simply put the client-specific constants and variables in separate settings.py files and then choose which file to use upon deploy. This makes it easy for me to maintain the server app for different clients.
I'm wondering if there's something similar that we can do for iOS and Android projects.
For android there's a fairly straightforward method which is a built in feature: build flavors.
You'd specify an additional flavor for one of the clients and keep the main flavor for the other client.
Then add copies of the files that need modification in the corresponding folder of the flavor.
Here is a thorough description of flavors and how to do it for your specific requirement:
http://blog.robustastudio.com/mobile-development/android/building-multiple-editions-of-android-app-gradle/
Android's documentation on build flavors: https://developer.android.com/studio/build/build-variants.html#product-flavors
For iOS I would use pre-processor commands to call different code for different clients. I would also write a script (I wrote mine in swift to run in Terminal on the Mac) that will take in settings and make changes to .plist files and project files depending on parameters you give the script
I have worked in the same environment and faced the same problem . Follow the below procedure and it should work like a charm :
Step 1 . Create a Package and declare it as a library .
Step 2. . Create a module and declare the above library in dependencies .
Step 3. Create another module and declare library as a dependency .
Now you library code is the base code for both modules . Whichever are the client specific changes you want to perform can be performed in modules .

Android load modules dynamically

I wanna write an android application which can be extended with modules (android libraries). The modules shall be loaded at runtime. Therefore they'll be downloaded from an url and stored in a directory.
The modules are aar files.
Is there a way to load aar files dynamically at runtime?
I know it's possible to just load the contained classes.jar with an URLClassLoader. But than I can't load the layout, string, ... resources. HM
Does anyone know a way how to solve this?
EDIT:
I found a few related topics:
Dynamically loading aar library
https://stackoverflow.com/questions/25919338/is-possible-to-include-a-dynamically-aar-file
Write Plugin for Android App
Plugins architecture for an Android app?
How to develop an app that has add-ons?
Android - Build an application that supports add-ons
It seems that it doesn't work because of the answer from the first link. I hope I'm wrong with that thinking.
I'm having a kind of similar problem.
i want to add plugins on runtime without forcing the user to reinstall the app.
I found a very good chapter called "Plugin Patterns" on "The Busy Coder's Guide to Android Development" book. I am still reading it so can't really say if it covers exactly your needs but it contains plenty of information that might be useful for your case.
Here is a sample of the chapter, found on the books web page, so you have an overview of what it covers
For the purposes of this chapter, a “plugin model” refers to an app (the plugin “host”) that is being extended by other apps (the
“plugins”) that are largely dedicated to that job.
Certainly, there are plenty of ways that apps can work together
without one being a plugin to another. The user’s Web browser is not a
plugin of your app when you call startActivity() to view a Web page,
for example.
By contrast, the Locale app can be extended via plugins, written
either by two forty four a.m. (the authors of Locale) or third
parties. These plugins have no real value to the user other than by
how they improve what Locale itself can do. This sort of structure,
therefore, qualifies as a plugin model.
In particular, this chapter will focus on two general scenarios for
wanting a plugin model, though others certainly exist:
You want to allow third parties to extend the capability of your app,
much as two forty four a.m. wanted with Locale, or You want to reduce
the number of permissions in your core app by delegating some
permissions to plugins, so users can “opt into” those permissions
I hope that helps a bit.
There is a gradle plugin that can help to decouple aar into resources and dexes. Check this out When you are building your project with inject dependency this plugin extract aar and merges resources with your project resources, than merges manifests and after that collects all jars(inside each aar and just jar dependencies) and creates a dex file which you can upload to any server and at runtime download that dex and load.

Is it possible to add a externally-maintained project library, without copying?

I'm working with Android Studio 0.5.8.
I have a Working project, and I want to reuse all its contents to make an almost identical app with only another name and different colors.
Basically I want to make a library from the original app and reuse it in various identical apps, but I don't want to copy & paste inside each new app, I want to maintain and develop only one codebase (the project library).
I have read and read, but I can'tt find any real solution.
I tried this in my settings.gradle:
include ':AppCopy1', ':..:LibraryProject'
It works, but I cant use any classes in AppCopy1.
This sounds like a good candidate for Product Flavors. The Gradle build system has support for maintaining a single codebase and building multiple apps from that codebase that only differ by a few files changes. See the configuration examples here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants for details.

Manage code/build for Android app stores (Google/Amazon/etc)?

I have an Android app that's downloaded primarily from Android Market (now, Google Play). We made a few tweaks to the source and also submitted to the Amazon App Store to see what sort of traction it gets. I'm now looking for a sustainable way to develop from a common code base and yet build so that I can submit to either/both.
Amazon's store has some restrictions about available APIs, and hence I'd like to conditionally remove/modify features from that version. Since Java doesn't support traditional conditional compilation, and conditionally including files in Eclipse doesn't seem trivial (is it even possible?), I wanted to ask what others are doing to solve this.
Admittedly, I'm no Eclipse/Java expert so feel free to school me.
What I'm looking for in a solution:
Building/debugging using Eclipse.
Static code files, with environment/settings toggles to control what to build.
No duplicate code or conditional logic in code to pick code flow at runtime
Is this something you've solved for Android apps specifically, or for other Java/Eclipse based projects? Suggestions for where to begin?
It's quite easy to do in the newest versions of ADT (version 17), though I do find it makes compilation a bit longer:
Create a new Android project (proj-A)
Go to Project->Properties, select Android, and check "Is Library"
Move all your common code to proj-A, import all the necessary libraries
Create a new Android project for Google Play (proj-B)
Go to Project->Properties, select Android, and add Proj-A to the Library
Repeat #4&5 for the Amazon version
If you have some variables that should be set differently for each sub project (i.e. boolean GOOGLE_PLAY_VERSION to enable Google Play specific functions), you have to create another project to contain these values since you can't have projects that reference one-another in a circular fashion. You can solve this by adding the following steps:
Pull all of your sub-project specific variables into one or more Classes that just serves as container(s) for these variables
Create a "dummy" Java project (dummy)
Config proj-A to add a new Source link to the bin directory of dummy
Add the config Classes in each sub-project with project-specific changes
Profits!
Note that the variables in dummy should not be set as final, otherwise it will override sub-project's setting.
This may seem like quite a bit of up-front work, but has worked quite well for me as far as version control goes.
Edit:
Now with Google's move to Android Studio & Gradle, it may be better to move to that if you are starting a new project if you want to support multiple APKs, see Android dev site's Building Your Project with Gradle#Work with build variants. It definitely doesn't hurt to evaluate that option before deciding.
Unfortunately, it's sort of a convention in Android to change flow at runtime based on what would be in C/C++-land conditional compilation.
Our app has to maintain different behavior for different API levels, so we've created some application-level constants that are initialized statically based on API-level information available to us, and used throughout the code. This is the way that Google does things in their examples (for example, see the ActionBarCompat compatibility library, and in particular the factory method used here).
You could create an interface CustomBuild, and implement it in AmazonBuild and GooglePlayBuild, then use a static getBuild() method to switch functionality as necessary:
if(getBuild().shouldEnableFeatureX()){
doStuff();
} else {
doDifferentStuff();
}
Then all you've got to worry about switching between builds is a line or two of code in the factory along with maintaining which things you want enabled in which versions. Or you could include a different version of a static class CustomBuild for each build.
I'm going to second the suggestion of others above re: switching to something like Maven for building; it should make your life much easier once you have it set up.
I'm also going to say you should make the core of the app a library as suggested above, and have two different modules (one for amazon, one for play store) that depend on the library but each only contain the one custom factory file (or just a static class for each type of build that contains the same "should I do this thing?" methods... once you have the infrastructure it's just a matter of preference).
I haven't actually tried this yet, but it's something I've thought about.
How about using Eclipse's ability to link to files from a directory outside your workspace?
Start with one Eclipse project: for the sake of argument, say it's the Google Play version.
Now build a second project, beginning with asking Eclipse to link (not copy) the source files from your first project.
To develop the second project, add classes that subclass ones from the original project to realize your modifications. For resources, you can use some combination of includes, attribute overrides, and selectors.
Where it's not possible to subclass or extend, then obviously you'll have to just copy the original source file and hack on it. If you're really OCD about it, you can probably just maintain a patch set rather than a whole redundant set of files.
What do you think, will it work?
You may create manually two projects in Eclipse pointing to the same source folders but with different inclusion/exclusion filters and different target directories.
Then two Ant targets using properties to switch excluded files from javac fileset are enough to generate corresponding jar files.
The aim is to get a clean application for each target, without any code from the other one.
With features listed as pluggable behaviors in a property file or XML configuration, your runtime will adapt itself with the addition of menu entries.

Multiple Android Application Package .apk files from single source code

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:
Packaging shared code into Android libraries or into external Java jars
Producing a debug vs. signed release .apk
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?
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
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/
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.
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.
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.
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.
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.
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.
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.
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.

Categories

Resources