android – Maintaining both free and pro versions of an application-ThrowExceptions

Exception or error:

I want to create a PRO version of my application for Android and was wondering how to structure my repository.

For know I have a trunk and feature branches. I’d like to put a pro version in another branch but maybe there is a better way? For example, maybe I should create two branches – one for free version, the other for pro?

Pro version will have additional features and will be ads-free, so eg. I don’t want to include AdMob libraries in the pro version.

Do you have any experience or suggestions as to what would be the best way to structure the repository in this case?

EDIT:
I think I’ve found the best solution (for my app) in this thread: http://groups.google.com/group/android-developers/browse_thread/thread/4ad3d67f735f16d7/948b4f9eee2490a3

The trick discussed there is about having another application that only serves the purpose of unlocking PRO functionality in the actual application. The unlocking app is paid in the market and the actual app merely checks for the existence of it on the device.

How to solve:

I know you have already made your decision, but I have another suggestion that might help others.

I use git for my repository. Creating and maintaining branches is very easy. I have my master “pro” repository, and a “free” branch. I make all code changes to the master. My “free” branch only differs by whatever changes trigger the “free” behavior.
Whenever I’m done making changes to the code, I commit it to the master branch, then switch over to the free branch and use the “rebase” command to catch it up with the master.

It rolls back the change that makes it behave as the “free” version, applies the changes I made to master, then re-applies the “free” changes.

I don’t have to maintain two versions. I don’t have to remember to toggle some switch, or make the same changes back and forth. It’s pretty slick, and I like it better than a second app that triggers the pro behavior because I can strip out libraries that aren’t needed for the version in question.

###

I would suggest not maintaining two branches, but have either runtime or compile time switches to disable the PRO functionality for the free version. You could even remove not required DLL’s when building.

Maintaining two branches means fixing problems in two places, which will become more of a problem as the branches inevitably diverge.

###

I found an easy way to do this in eclipse. I was quite surprised at how easy it was once I discovered it.

  1. In project properties for com.app.free check the “Is Library” as true (you must have compiled the project at least once before changing this otherwise you get an error saying that library projects cannot be compiled, if you do get this error simply un-check it, compile, then re-check.
  2. create new project com.app.pro
  3. add com.app.free project as a library in the project settings in the android section of the pro porject
  4. create new class MyApplication in com.app.pro and extend Application
  5. override onCreate() NOTE: For those fellow copy/paste’ers this is NOT the same as the onCreate(Bundle savedInstanceState) bundle of an activity. You must remove the Bundle argument as this is an application not an activity.
  6. Then add or set the static variable which will be read in the validation method to validate license. EX: IS_PRO = true; then validation method reads variable and returns true if IS_PRO is true.
  7. Copy manifest contents form com.app.free to com.app.pro
  8. add android:name=”MyApplication ” to the application tag in the com.app.pro manifest
  9. append com.app.free in front of name attribute for all activities. (this makes the application know that your activities are to be found in the library package which is the free version) EX: android:name=”.MainActivity” => android:name=”com.app.free.MainActivity”
  10. Now compile and you have a pro version

This method assumes you are using a global validation method. For example I created a class that connects users to a DB hosted on my domain which determines when the user first installed the app. For any pro only activities I check LicenseClass.isValidLicense() which compares dates and return true if its been less than the desired number of days. in the isValidLicense() function I check if Application.IS_PRO is set to true and return true if it is.

So now you can make as many changes however often and all you have to do is recompile both. The only thing to keep in mind is what ever changes you make in the com.app.free manifest have to be reflected in the pro. But this is the case with any application because android apps require you to declare which activities you are going to use no matter what.

NOTE: You may delete all assets and resources(dont’t delete the res folder itself though) that are auto generated at project creation as they will not be used. Also, the only class file needed is the MyApplication file from step 3. Which means you may also delete the MainActivity.class that is auto generated as well since it is also never used. You may also remove any tags that are not used in the used in the pro version. EX: I have a BuyPro activity which opens if validation fails. Since validation will never fail in pro version it is not required. Of course all these deletions are optional just letting you know what I’ve learned.

CONS: The only con I found so far is that you can’t use switch statements with your resource variables because they are no longer constants. So when you use a project as a library any variable you create in your strings.xml file for example are automatically overridden if you declare a variable of the same name in the pro version. For me this is not a con because I don’t like using switch states in java because they limit you to switching on int type only and they require constant values. Which means in java I usually have to us if … else staments anyway. Plus Eclipse will actually help convert switch statements if you put your cursor on the switch key word and press Ctrl+1 then click convert to if else. Also, I find it pretty useful that the resources are overridden because you can do things like change app_name from “app free” to “app pro” or upload a new drawable for say the app icon simply by creating the new version in the location where it exists in the free app. EX: if the res/values/string.xml contains say 100 string variables but all you need or want to change in the pro version is the app_name simply recreate the res/values/string.xml (NOT copy) and add the app_name variable. Now the app_name variable in the free version will be overridden which means the string.xml file in the pro version only needs to contain the 1 variable instead of 100 since its the only variable that changed. Easy Peasy. 🙂

EDIT: I found out eclipse doesn’t let yo export .apk’s for libraries so you have to un-check the “Is Library” option in the free version after you’ve added it as a library in the pro version. As far as I can tell the only thing this does is causes eclipse not to warn you about the switch statement issue. Other than that it seems to work just fine.

###

Have a single version with public static final boolean IS_PRO that would determine free/pro behavior.

EDIT:
The package thing. Say, all your classes reside under com.myapp.android.free.
Then, in AndroidManifest.xml you declare package="com.myapp.android" for the paid version and package="com.myapp.android.free" for the free one.
If you use full names for activities, services, etc., you won’t have to change anything else.

I wouldn’t bother removing unused libs from the paid version. If you do, you’ll have to do this manually.

Leave a Reply

Your email address will not be published. Required fields are marked *