I am using Mercurial (with TortoiseHG) to manage my Android project and recently had to branch it due to the app getting a parallel, branded version with different package name.
I have done some research and succeeded in separating everything, but now after a few days I am starting to find it hard to maintain both branches. Any change in com.myapp.firstbranch needs to be transited to com.myapp.secondbranch manually.
Worse still, I have every reason to suspect that more branches are to follow, which would require me to introduce any changes and bugfixes between many branches.
Does Mercurial and/or Tortoisehg offer any support for such situation? A simple merge does not work, because of different package names (the VCS sees everything as separate files and puts two versions of the app in one folder).
Ideal solution would be a tool which would allow me to sync only selected parts of selected files with no regard to imports, packages and so on, just plain text replacement.
I can't imagine (please explain deeper), how different package name can interfere with Mercurial branches. You have different trees inside repo? Or renamed files in branches (anyway, Mercurial track renames and can correctly merge renamed files in branches)?
When I faced such task (maintain different customer's branches, based on historically common codebase), I finished with MQ-patchset (patch per target for customer-specific changes) and single branch with common code in changesets
You can create+define different merge-tools for your repo, which will merge different files according to different (your) policy, not just interactive merge in GIU-merger (see internal:* mergetools as example)
Additions
I'll ask to show (at least part of) hg manifest for branches (or just ls of Working Dir) (just because I know nothing about packages, it's structures and Android-development in common), but, AFAICR, if you have /firstbranch in initial branch, which in second branch was renamed to /secondbranch, Mercurial will honor this change in branch-merges. Another idea is eliminate parent-tree from versioning as much as possible and move task of creating proper tree of package into build-tool
No, I had "trivial" tasks of adding|changing|removing objects (customer's branding), but, from my POV, "all imports, package relations and so on" are, technically, just changes in code (and possible - trees), which patches can hold
Custom mergetools have to be mostly easy hand-made scripts with minimal logic in it. Try to read Wikis: Merge Tool Configuration (part 2) and Merge Tools as starting point and this excellent example of creating own merge-tool for merging .hgtags
Related
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).
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.
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.
Imagine mobile application that is planned to be implemented for both iOS and Android.
Development was started from the iOS version only and now the time has come to start with Android one.
iOS application's code is stored at its' own Git repository that named after the apps name, e.g. "MYApp".
Now I would like to create one common repository for both iOS and Android applications and name it again after application's name: "MYApp".
It is not a problem at first glance.
Just create repository, create 2 subfolders there and start working.
But.
I would like that Android developer could work only with his folder and iOS developer only with his one too and both of them could see only their own folders related history (log).
I worked with SVN previously.
Usually I created subfolders and you could checkout any of them to work only with this subfolder.
History was also filtered to your scope.
I'm stuck with implementing the same under Git.
Please, help me to find right direction.
I will sum up solutions suggested.
Use branching for different platforms. I don't think that it is good idea, because branches used for another purpose. It seems to me very "jacky".
Use submodules. Just create as many repos as platforms you are targeting to, name them "MYApp-iOS", "MyApp-Android", etc. and finally end up with "master" repo, that could be names as "MYApp" (without any suffixes). Then add all related repos to "master" one with git submodules feature.
Use git slave. Investigating...
Please, feel free to edit this list to brainstorm the problem.
There is a way to keep to kind-of-related separate projects in a same git repository utilising git branching.
But keep in mind that that is not why branching was implemented into git. One of its uses would be development of a radical new functionality to your app that might not see the release any time soon for example.
On the end: it is a matter of opinion. If you are prepared to administrate a more complex repository just to keep both codes on the same place - you can.
I would definetly make two separate repositories though. Couple of opinions on this topic can also be found here on SO: Git branches with completely different content
EDIT:
gitslave seems to tackle your problem. You might want to give it a try.
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.
I have an android application targetted at business customers in different countries.
I need to customize the application slightly for these customers. At the moment I created a customization.xml file (string resource under res/values) that will contain these custom fields.
Currently I havent found a way to make these customer dependent (also note that they need to be in xml files).
Can I branch only the customizations.xml and androidmanifest.xml files in git? These files are pretty small, so i can easily maintain them in different branches. However the other changes to the project should be easily pushed to different branches. How would i go about doing that?
Say we have a:
default : master branch
customer1 : customer1 branch with a different androidmanifest.xml and customizations.xml
customer2 : ....
Thanks for your insights. (I'd prefer git to solve this, but if you know another way, please elaborate).
Git is snapshot based and will store the entire tree structure per commit. However, it stores contents based on their hash values. This means your changes will add minimal size to the repository.
you can only branch the full project. however, nobody prevents you from changing just those two files in the branch. you can then simply merge those branches to propagate the changes.
There are two problems you are trying to address here: 1) Optimal versioning strategy for doing releases for different countries. 2) Customer dependent customizations, done by user from the app.
For 1) it is recommended that you create a branch, make necessary changes and do a release from it. That way you will be able to have a clear snapshot of what is in the release in case you need to do bug fixes. It will also adequately address the customization and versioning needs you will have for this.
For 2) loading custom UI for users can be done by prompting the user on first launch of app to select from a set of options. You can then save this in app preferences. Make sure to provide an option to change this in some sort of settings menu.
Hello I am a beginning android developer using windows and the eclipse IDE to develop java android applications.I have published one game but there is a free version of the game and a paid version. The google market insists that the different versions must have different package names. So far i have been refactoring the package with 2 different names and changing the R resource file import each time i build the different versions. The code is 99% the same for both versions.Is there a better way?
You have various discussions on this topic here and there, but basically the solution is akin to duplicate the project.
For instance (not based on eclipse):
It is difficult to answer this, since we don't know what the difference is between the free and not-free versions of your app.
I'm going to assume that the differences could be handled by some sort of global free/not-free flag. By that, I mean that the same code would make up both versions of the app, and which portions are enabled or used would be dependent on some public static data member somewhere:
if (SomeClass.IS_PAID_APP) {
// add more stuff to menu, etc.
}
If you can organize your app that way, then you only need one code base.
Have it set to build your app one way (free or paid, your choice) and with the proper package in your manifest for that version of the app.
Then, add an Ant task that does the following:
Makes a tree copy of your project dir to a temporary location
Switch the copy of the manifest to the new package name via a
search-and-replace
Switch all import statements for your old package's edition of R to
the new package, again via search-and-replace, and again on the copy,
not your original
Change your IS_PAID_APP (or whatever) to the opposite value
(search-and-replace in the copy)
Executes an Ant build for the copy of the project
Copies the binaries from that build to the main project's bin/
directory under a distinct name (so it doesn't clobber your other copy
of the APK)
Deletes the tree copy made in step #1
If Java had a pre-processor, this would be somewhat simpler. However, the basic technique that I describe above has been used for a couple of decades now. It's clunky, but it works, and it means you only have one set of source code to deal with.
Note that the Ant <replace> task would handle your search-and-replace stuff nicely.
This is one of the failings of Android Market though I can see why they did it that way. It just wasn't designed for having Free and Paid versions of your app (they claim the 24hr return policy is what this is for, but that's instead used for piracy)-:
Anyways, simplest thing to do is to write an Ant build script (or whatever scripting language you use). Do a search replace of your package name through all the .xml and .java files. Then do the build of your app there. Refactoring your code is more pain than it's worth IMHO...