I'm trying to find the best way to build/package an Android app for 6+ different customers. I could use different branches in SVN for all of the customers, but the only difference between the apps are some values in the resource folder (drawables, strings, etc).
I wrote an ant script that imports the standard Android build.xml. This script does the following:
Reads the customer names from a properties file.
For each customer the following is done:
The package name in AndroidManifest.xml is changed (by hooking into the -pre-build target).
The custom resources are copied into the res directory in the build (by hooking into the -pre-compile target).
The package name is changed back to the default value (by hooking into the -post-compile target).
The APK is copied to a specific location an named something like customer-versionno.apk.
This seemed to work well until I just now wrote the part that changes the package name. Because of the package name change the location of the R class is also changed, meaning that the build fails as the Java classes import the R class from the standard package.
I don't want to have a build script that changes code. I want to be able to do this with minimum changes to any files.
Soo..the questions are really:
Are there any good/simple solutions for my problem?
Am I approaching this problem in the wrong way? Are there better ways to easily package the same app to 6+ different customers?
Do you really need to change the package name? Changing the package name is a pain to do automatically. That being said, here is my solution to the problem:
My scenario is that I have one app that gets deployed to 30-200 different signed APK files where the only difference between the files are some resources (drawables, strings, values etc), and the package name.
I do this by working on a generic version of the app that serves as the template project. Once this works and I am ready to deploy I invoke a bash script that loops through the following steps for each target:
Clean the project completely
Swap out res dir and package name using sed.
Builds and signs the APK
This balances the horrific deply time with fast developemnt time. I really don't see another more elegant/robust solution than this.
And finally a small tip: In android manifest use relative package names like ".Application" instead of "com.mycompany.myproject.Application". This way you only need to change the package name in ONE location.
Is it possible to solve this with making 6+ different projects that includes your main projekt. This way you are able to override resources and make different apk's
Related
We have an Android project where we maintain a single code base for different customers, what will be the fastest/most efficient way to compile for different customers every time? Few options I found and my questions:
writing scripts: to replace resources folder and edit app name, version, etc.
Using Android Library Projects It is gonna be quite impractical to separate current project as Library projects, I am thinking whether it is possible to save some settings and resources files as a Library project and just import different library projects for different compilation?
Storing settings and resources on a remote server Is it possible to store resource files and some app settings (xml, constants, etc) on a remote server, and download them and replace to the app when the user first launch the apk? Where will these files be stored?
Any other options you would suggest?
Android Studio provides a feature called "flavors" that allow you to quickly define different configurations from a single code base. I have just learned about this in the last couple of days, so I don't know a lot more than this.
The best way I've found is a post build script step. Use a default set of resources/assets for your main build. This is your default apk, use it for default testing. Save the unsigned apk this builds. Then for the customer specific APKs, open up the unsigned apk (its just a zip file), overwrite any overwritten files, then sign the new version.
This works fine so long as you don't need to change code for different customers. It also doesn't put any unneeded assets/resources in any build, so you don't leak info to one customer about your other customers by including their files.
If you do need to change code, the best way is to do a runtime check on a variable from a settings file. And overwrite the settings file the same way you do everything else.
As an added bonus, if you need to you can write a very fancy system that would allow the customer to upload his own files to override your defaults (including allowing them to override some of your settings), so you don't need to deal with a dozen change requests. That requires a lot more work though.
I need to create two different Android apps using the same code. The user should be able to install both the apps on the same device.
The differences between the two apps are just a few strings, including the application name. These strings have been isolated to a string resource file called Custom.xml.
My plan to achieve two versions is rather simple. In the nightly build script:
1. Run Ant to create the first application .apk file.
2. Rename the generated .apk file
3. Replace Custom.xml with a different one
4. Run Ant once again
This may work except for one thing that I am not sure about. It is the package name in AndroidManifest.xml->manifest->package attribute. I guess this has to be different if the apps have to coexist. Does changing the package name have any impact on the rest of the code? I hope this package name is not tied to the package name used in java files.
Also, does anyone see any problem with my overall strategy? Thank you in advance for your help.
No, it does not have any impact, unless you use your hardcoded package name in the code.
There is an official example of renaming the package to build a debuggable version of the app.
We hope to build multiple applications based on the same source code. The base source code will be stored in SVN so at daily development we just need to modify one codebase.
While for different customers, we hope to given some some level of branding. Mostly changing images and titles, these can be done by just change the resources.
After some research, We find that it is really touch to do these multiple version applications. The main problem is that R.java is generated based on the package name. And package name identify the application. In the source code there are many files import this package.name.R, which means for different application, there will be different package name, and different R's reference need to be change in most source code file.
We find some articles on web about using Ant to do this task, but none of them are really specified. We hope someone could help!
Generally the workflow will be like this:
Changing the package name in AndroidManifest.xml
Go over all source code file, find and replace anything referenced to R to the new package name.
Switch the res folder to the new client's res folder (We will have this folder ready)
Auto generate R.java file.
Start normal compile and build process.
Get Apk.
We hope someone could point out how can we achieve these task by using Ant, or any other better solution.
Thank you!
I think you should create an Android Library Project (http://developer.android.com/tools/projects/index.html#LibraryProjects) with the common code, check it into VCS, and then create separate projects for every customer which you should also check into VCS to keep track of them.
You will be able to generate different customized versions from same source code.
I am developing Android application for which I want to ship several different apks for different languages in the market (every language includes a huge bundle of files and I want to avoid creating one huge apk with all language bundles).
So what I need is to customize a bit the Manifest file for each language: e.g. the package of the application and possibly the application version etc. I know how I can template the manifest so that I can manually insert my values in certain points in the file (see this post). The problem is that I use ant for preparing my production apks, but otherwise I develop using Eclipse and so I need my project working in the IDE too. Eclipse requires complete Manifest file and will not understand of the templating I will use for the ant builds as far as I know (please somebody prove me wrong).
My problem is that I want to avoid maintaining two manifest files that are identical in large part (one templated and one complete for Eclipse). Currently I can think of two possible approaches, but I do not know how to accomplish them:
Use some kind of definition injection in the manifest file: if I am able to inject certain xml file in the body of AndroidManifest file, I can keep the identical part in one xml part and customize only the points of difference
If it is possible to configure Eclipse to use some sequence of ant tasks to build Android projects instead of the prebuild routines I might be able to integrate the way I build my production apks in the IDE.
Please if there is anyone who knows how to accomplish any of the above two, or has any other idea how can I solve my issue: help!
Take a look on ant replace task:
<replace file="${build.out}/src/config.prop" token="###" value="${build.version}-${build.type}"/>
But again you should be careful with values that they are unique.
You could also replace your eclipse manifest with generated manifest by echoxml task.
Or you could reuse this nice task about xml manipulation.
At the company I work for, we pretty much use the approach given by Eugen to automate the build process of apps that e.g. should simply be branded differently by exchanging certain assets, styles, strings and configurations. We tend to set up the project and build process as follows:
Create the Android project and set it up such that it works for a specific branding. This will make sure that you can still build and run from Eclipse. Assuming that the codebase does not change between differently branded releases, that should be fine.
Create an ant build configuration that:
copies any files that are going to be changed to a backup directory
modifies the project files according to a configuration file (see below)
compiles the project sources and signs it with a release key (if making a release build)
copies back the files from step 1, overwriting any changes and returning the project to its original state
Create configuration files for every 'branding', or language specific release in your scenario.
Basically these steps will allow you to create branded/partner/language specific builds by simply providing the appropriate configuration with the ant build command. In our case it looks somewhat like this:
ant partner-release -Dpartner=stackoverflow
where 'stackoverflow' will point to a configuration with the same name. In our case these configuration files are small xml files that contain all the parameters that are to be replaced for that specific build. It could contain strings, but might as well point to other files (e.g. logo images) that should be copied into the assets/resources. For example:
<config>
<version_name>1.00</version_name>
<version_code>1</version_code>
...
</config>
Some more pointers:
We use xmltask to modify any xml files in the project; e.g. the manifest and resources.
Since the aforementioned task is really easy to use, our build configuration files are also set up as xml files, as illustrated above. It's quite human readable and easy and straightforward to change.
You can also use replace and ReplaceRegExp tasks to change configuration-dependent variables in almost any file. The latter can be especially convenient to make build-time changes to source code.
I have been using apktool to decompile apps and make changes to better fit my touchpad.
One app in particular (swype) I would like to make a duplicate of with a different size keyboard I can switch to. I have tried changing in the manifest.xml any reference to com.swype I changed to com.thumbswype but when rebuilding the app it says some error about PathNotExist.
I also tried changing the app_name inside res/values/strings and while only changing this allowed me to rebuild the app It still wanted to overwrite the existing swype when I installed it.
The manifest is referring to class names in the compiled code, which would be in package comp.swype. So when you change the manifest but don’t change the compiled code, it can no longer find classes with the specified fully-qualified names.
And the Android system uses fully-qualified class names to identify installed apps. That’s why you can’t have two apps installed at the same time using the same fully-qualified names.