2

I understand that the best way to develop a free and paid version of you app is to have a library project which contains the main bulk of the program. The free and paid projects will then use this library project. This allows the free and paid projects to have different resources.

However, my question is how do we limit functionality within the free app (or extend it for the paid app)? For instance, my free app will only be able to access the latest row in a database table whereas the paid app can access all the rows.

One way to do this would be to have a boolean flag in resources somewhere that you set to true for paid and false for free. At runtime the library project checks for the boolean flag and alters behavior accordingly. However, this seems very easily to hack for any potential attacks. Are there better ways?

Would this be easier to complete with one free app and then use in-app billing to unlock the pro functions?

tshepang
  • 12,111
  • 21
  • 91
  • 136
James Cross
  • 7,799
  • 8
  • 24
  • 30
  • -1 because duplicate of http://stackoverflow.com/questions/3711967/best-way-to-have-paid-and-free-version-of-an-android-app – rds Aug 27 '12 at 09:13

3 Answers3

4

IMHO, Java/Android does not make it easy in this scenario. Ideally you should have one codebase, and able to compile a paid or free version at will. The free version will have critical methods/classes disabled, so that no one can tinker with database or xml to enable full functionality of the app.

One way to do this is with conditional compilation, which again, Java does not support. However, there are some Ant tasks that can do this, e.g. http://prebop.sourceforge.net/doc.html. You can add something in the code like this:

/* $if paid_version$ */
public void paid_method() {

}
/* $endif$ */

The above code will get removed, if the ant target you are building does not have the variable paid_version defined.

How to setup prebop is another topic altogther, it's complicated but worth it to have a single codebase.

Update May 2013: The new Android build system based on Gradle makes building paid and free APK slightly easier. See Android Tools website for topic on 'Build Variants'. In short, you can structure your source like this:

/src/main/
/src/paid/
/src/free/

All the shared code reside in /src/main, paid code in /src/paid and free code in /src/free. The build system will create paid and free APKs for you. However, one feature that is still missing is the ability to do conditional compiling in the source itself. As of this writing, the Gradle build tool is still in beta state, so hopefully this will get added in the final release.

azgolfer
  • 15,087
  • 4
  • 49
  • 46
  • This is a very good solution. Unfortuanlty after spending a day trying to understand how ant and prebop works I have given up and going back to using Android library projects. – James Cross Jun 24 '12 at 08:19
  • Dont' give up just yet. It took me a week to get it setup properly. The key is to learn how to do basic ant builds first. Once you're comfortable with ant, you can add all sorts of ant-tasks that can manipulate the project during build time. e.g. you have a boolean flag to enable pro feature, right? You can have ant at build time set this boolean flag to false, which means the pro feature section will not get compiled. Then use a CI like Jenkins that allow you to spit out a pro and a free build every time you check in something. – azgolfer Jun 24 '12 at 16:13
  • 1
    This is great for protecting against illicit unlocking of your paid features. OTOH, not great if you want to incrementally enable those features with in-app payments. I also wonder how much of a threat it is that someone will convert your free app to a paid version? If your average user is not very computer-literate / hacking inclined, then what does it really matter if a few skilled individuals save a few bucks doing that? They won't end up with anything to post publicly than they couldn't get by just spending a couple of bucks and buying your app, and then spreading it around. Thoughts? – Carl Jul 02 '12 at 10:34
  • I haven't played with in-app payments yet, obviously if you have a chunk of code in the app that enables paid features, it's always at-risk to being decompiled and enabled by someone else. With conditional compilation, your paid feature will not appear in the free version so it cannot be enabled, but it probably won't work well with in-app payment. Finallu, you have to account for the fact once your apk is hacked, it can be redistributed to anyone, so it may not be only a few indviduals getting a free ride. – azgolfer Jul 02 '12 at 14:52
2

Never save any flags in Res or SharedPrefs which specify if an apps was paid. Rooted phones have access to those and can modify them. I also had this problem and wrote two separate apps (copied the paid one and deleted some methods, added ads and so on). This is the simplest solution.

paulgavrikov
  • 1,883
  • 3
  • 29
  • 51
  • 2
    This is not a very maintainable method. If you found a bug you would have to fix it twice. – James Cross Jun 22 '12 at 14:45
  • 2
    Well, @Styx, any decent source control management allows to merge changes from one branch to another. So, bluewhile's solution is perfectly reasonnable – rds Aug 27 '12 at 09:12
2

IMO your best approach to creating multiple app releases from a single source is to use a library project.

I've attempted this recently and it seems to work very well. Although I haven't tried releasing code based on this to Google Play, I've created separate apps which can both run at the same time on a test device, with their own icons.

Since separate apps on Android must each have a different package name, the easiest way to configure separate behavior is to test that package name in your library to see if it is presently running within the free or the paid version. That test can be made within a custom Application-derived object defined in the library project; the package name can be obtained there by calling getPackageName().

Your free and paid apps, at a minimum, may need only an AndroidManifest.xml file and a few resources (e.g., an application icon that distinguishes free from paid).

In the manifest for each of the two apps you will want the application element to have its android.name attribute set to the full path to your custom Application-derived class (as defined in the library). And of course you will want to have the package= attribute of the manifest element itself set to a distinct package that ends in something like .free or .paid, for the respective apps. The activity objects in the manifest can then have an android:name attribute that is set to the proper Activity-derived class in the library (using a full path).

The code that enables your paid features will then simply call the methods that test the package in your custom Application object, parse the package name, and decide on that basis whether a paid or free version is running, and then enable or disable the paid features accordingly.

There is a very helpful example (although somewhat old, still relevant) with full code, here:

https://github.com/donnfelker/FullAndLiteVersionSharedLibrary/blob/master/FooLibrary/src/com/example/foolibrary/FooLibraryApplication.java

Carl
  • 15,445
  • 5
  • 55
  • 53
  • Thank you for that response. In the end I have gone with a library project. Check out another question I asked and the answer I received. It might help you: http://stackoverflow.com/questions/11176113/android-free-paid-architecture-using-library – James Cross Jun 29 '12 at 11:19
  • In that other thread I was properly corrected for suggesting that variant behavior in the library could be conditioned on testing the package name of the containing app. It could violate modularity to configure library behavior based upon what module is *using* the library. So all app-*specific* information should reside in the app, when applying the approach described above. If you are just disabling features then it might be OK to do so based upon the app's package, but if you have, say, a dialog variant for free vs. paid then those dialogs should reside in the apps, not the library. – Carl Jul 02 '12 at 09:44
  • Regarding how this need (for a library project) evolves, I suspect that a dev typically creates a full-featured app and *then* decides to create a free version with disablements, and this results in most of the full app ending up in the library project, with a test of the app package in the library to control the disablements. This is arguably not ideal as you are loading unused stuff into the free app. OTOH, it's necessary if you want to enable features later on (e.g., with in-app payments). and it may also compromise coherence to divide the full app between the library and the app proper. – Carl Jul 02 '12 at 10:21
  • Not meaning to drone on, but regarding that last point above, philosophically it's interesting to consider whether the usual design requirements for modularity should be applied to require the separation of features that have been suppressed for the sole purpose of extracting payment from users. Modularity is usually applied to group *functionally* related features together. You might have code that pertains to any one of an entire class of tasks, and then just limit that code to a specific subset of those tasks for a free version. A switch works for that; separation is not required. – Carl Jul 02 '12 at 10:48
  • I never expected such a detailed answer and follow up. I went down the route that the library project contained the bulk of the functionality. The free app project was just a very small project that had nothing much in it at all except to give access to the various parts of the library project. The paid app project then had the additional functionality. The code in the other thread helped a lot for 2 separate parts. – James Cross Jul 09 '12 at 07:37