How can I use the paid version of my app as a "key" to the free version?

Let's say for example that I have some Android app that does X. The free version has ads or basic features. I want to have a paid version that removes the ads and adds extra features.

How can I use the paid app as a "license key" to unlock the features in the free app?

So the user would install the free app, then install the paid app to get the extra features, but they would still run the free app (which would now be unlocked). What's the best approach to doing this?


Solution 1:

Use PackageManager to ensure your paid package is installed. AND ensure your free package signature matches installed premium package signature. Otherwise somebody would be able to install unsigned app with package name matching your paid package name and unlock premium this way.

This post can help you to find your signature Detect if app was downloaded from Android Market

Solution 2:

I'm using this:

PackageManager manager = getPackageManager();
if (manager.checkSignatures("core.package.name", "key.package.name")
    == PackageManager.SIGNATURE_MATCH) {
    //full version
}

It's pretty simple and it works.

Solution 3:

Here's a simple function which checks for the presence of the Pro Key, and checks that the package signature matches the free version:

protected static boolean isProInstalled(Context context) {
    PackageManager manager = context.getPackageManager();
    if (manager.checkSignatures(context.getPackageName(), "com.your.pro.key")
        == PackageManager.SIGNATURE_MATCH) {
        //Pro key installed, and signatures match
        return true;
    }
    return false;
}

Code is from this forum post, based on the method outlined at yoki.org.

Solution 4:

As someone else pointed out, yes, you can use PackageManager to detect the presence of the paid 'key' app, but that's problematic if someone only installs the paid version, uninstalls the free version, etc. Users might get annoyed at having to keep around two downloads to make your one app work. FWIW, I think DoubleTwist Air Sync does it this way. I'm pretty sure the Air Sync app doesn't do anything except enable the functionality in the free DoubleTwist app.

A more practical route might be to have two separate apps, then give the ability to import prefs and data from one to the other using a ContentProvider and/or sharedUserId. You can then share most of your code using a shared library project. However this means both apps need to use a different content URI since two apps can't use the same authority, which is sort of a pain, because your shared library code can't just have a static CONTENT_URI or AUTHORITY field like you'd normally find in a ContentProvider implementation.

I'm starting to think two separate apps with two more-or-less separate codebases is the way to go, because copying code between two projects might actually be easier than trying to maintain a shared library with all sorts of switches to enable or disable features between a free and paid version.

Actually, edgman's recommendation for using a single app and using licensing is probably the best way to go about managing a free and paid version of an app. It solves all of the problems listed above, although to be fair I haven't used licensing yet myself.

EDIT licensing appears to only be allowed for paid apps (bummer) so it's a no-go if you want to offer a free version. However in-app billing might be the "right" way for you to manage a free/paid version. Maybe it's Ok for the OP but I don't feel like requiring two apps to always be installed on a user's device is ideal. If a paying user installs the app on a new device, it appears to be possible to download prior transactions so they don't have to pay twice.