Best way to have paid and free version of an Android app [closed]

Solution 1:

The Android SDK formally addresses the issue of a shared or common codebase with something called a library project.

http://developer.android.com/tools/projects/index.html

Basically, the shared code is defined as a library project, then a paid and a free version are simply two different projects in your eclipse workbench, both referencing aforementioned library project.

At build-time, the library project gets merged with either of your releases, which is what you want.

The Android SDK example source code contains a project called TicTacToe that will help you get started with library projects usage.

Good luck.

Daniel

Solution 2:

Several approaches exist, but you usually don't see the drawbacks until you try them for yourself. Here are my experiences:

  1. Unlocker app. This is very easy to implement, create a new app that acts as a licence: your original app should check if the unlocker app's signature matches that of your app (if yes the unlocker is available on the device, otherwise no); your unlocker should prompt for downloading your free app if not installed, otherwise start it and remove its launcher icon.

    Pros: easy to implement and there is only one codebase to maintain.
    Cons: it is said that users are sometimes confused by this model, they simply don't understand why they have two launcher icons, or what have they just downloaded. Removing a launcher icon is cumbersome, changes are only visible if the device is rebooted. Also, it seems you will not be able to use Google's licensing API (LVL), because your free app cannot make licensing requests on behalf of your paid unlocker app. Any workaround for this latter leads to bad user experience.

  2. In-app purchase. This is easy to implement if you have IAP in your code anyway, otherwise it will take quite some time to get things right.

    Pros: there is only one codebase to maintain and purchasing flow for the user is quite convenient.
    Cons: users are said to be concerned about whether their purchase is 'persisent', meaning they are confused whether they could still use the pro features if they later installed the app to another device or reinstalled it.

  3. Free and paid versions with shared library project. This should not be a hard thing to code and seems like a logical decision to have a single codebase containing most of your app logic and maintain only the differences.

    Pros: users are less confused with this model, but they are probably concerned about whether their preferences will be lost if they start using the paid version.
    Cons: Java/Eclipse in my experience is not really friendly when it comes to libraries. It will take some time to set up the projects correctly, but it will still be confusing how the whole thing works, what to put in which manifest, what happens with resources, etc. You will face build issues with misconfigured projects, build issues with resources not being found (library project will not 'see' already referenced resources, so you'll have to edit the references one-by-one). Moreover asset files are not supported in this model meaning you will have to do some tricks with symlinking, copying or other magic that will just add to the terrible mess your "single codebase" project has already become. And when your project finally builds you just have to keep fingers crossed for the whole thing to work as expected, be prepared for missing images and hidden errors to look for. And of course you will need to provide your users a convenient way to migrate their preferences into the paid version upon first launch.

  4. Free and paid versions with separate codebases and source control. At first glance this also seems a good idea since a decent source control system could lift weight off your shoulders but...

    Pros: same as 3.
    Cons: you will be maintaning two different codebases and nothing else but a merging/branching hell that is to be expected here. App package names should be different, so you'll probably need to differentiate every single file you have, to keep things clean. And of course you will need to provide your users a convenient way to migrate their preferences into the paid version upon first launch.

  5. Free and paid versions with a script that derives one from the other. It sounds like a dirty hack to accomplish, but you know for sure that it works.

    Pros: same as 3 plus you only maintain a single codebase.
    Cons: creating the scripts takes a little time (make sure you rename folders, replace package, application and project names) and you'll have to be careful to update your scripts from time-to-time if necessary (this won't happen if there aren't too many differences between the free and the paid versions). And of course you will need to provide your users a convenient way to migrate their preferences into the paid version upon first launch.

No solution is perfect, but the above can hopefully point you in the right direction if you are just about to start implementing one of the possibilities.

Solution 3:

With Gradle build system, you now can have different product flavors, each having its own package name. Following is an example gradle script having free and pro flavors of the same app.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "19.1"

    defaultConfig {
        applicationId "com.example.my.app"
    }

    productFlavors {
        free {
            applicationId "com.example.my.app"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 12
            versionName '12'
        }
        pro {
            applicationId "com.example.my.app.pro"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 4
            versionName '4'
        }
    }

R class will still be generated in the package name specified in the AndroidManifest.xml so you don't need to change a single line of code when switching flavors.

You can switch the flavor from Build Variants pane which is accessible from left bottom corner of Android Studio. Also, when you want to generate a signed APK, android studio will ask you the flavor you want to build the APK.

Also, you can have different resources for each flavor. For an example, you can create a directory pro in your src directory. The directory structure should be similar to the main directory. (Eg: if you want to have a different launcher icon for pro version, you can place it in src\pro\res\drawable. This will replace the free icon located in src\main\res\drawable, when you have switched to pro flavor).

If you create a strings.xml in pro resource directory described above, the main strings.xml and pro strings.xml will get merged to get a final strings.xml when building in pro flavor. If a certain string key exists in both free and pro xml, the string value will be taken from pro xml.

If you need to check whether current version is pro or free in code, you can use a method like following.

public boolean isPro() {
    return context.getPackageName().equals("com.example.my.app.pro");
}

For more information, Refer this

Solution 4:

One source code two apps (Eclipse)

There is a recurring problem of managing an app with two forms of presentation in the market, maybe with only one bit difference between the two ( paidFor = true; ) Maybe the icon is different too.

This approach uses the description of Package names explained by Mihai at http://blog.javia.org/android-package-name/ which underlines the distinction between the package name used to manage the source code and the package name used to publish the apk on the Android Market. In this example the two published package names are com.acme.superprogram and com.acme.superprogrampaid, the Java source code package name is com.acme.superprogram.

In the manifest the Activities are listed and named as .ActivityName. Mike Wallace pointed out in his recent presentation that the preceding dot is important and it can be replaced by a fully qualified package. For example “com.acme.superprogram.DialogManager” can replace “.DialogManager” in the manifest.xml text.

Step 1 is to replace all the activity android:name entries with these fully qualified package names, using the java source code management package name (com.acme.superprogram).

Then the Manifest Package name can be changed...

In Eclipse this forces a recompile and a new R.java is created in the gen folder. Here is where it gets a bit tricky; there are two folders com.acme.superprogram and com.acme.superprogrampaid, only one has a R.java. Simply copy the R.java into the other folder so that the program can resolve the R.layout.xyz items.

When you change the package in the

I have tried it on a couple of apps. I have both running together on the emulator, my 2.1 phone and they are both on the Android Market.