How to develop two versions of the same application, one free and the other paid?

Asked

Viewed 2,508 times

17

I’m starting the development of an application for Android using Android Studio, I intend to make it available in two versions, one paid, with more features, and one free, more basic.

I thought about starting to develop and after finishing the base version, common between the paid and free application, create a copy of the project and start adding new features to the paid application, but I did not find this practice cool, because there would be redundant information (classes, images, layouts, etc) and whenever I find an error I would have to fix in both projects, if the same is in the base version.

I would like to know what to do in these cases and if there is any standard/tool to deal with it.

Note: base version are the common elements between paid and free version, this includes classes, pictures, layouts and all that.

  • 1

    Java, right? It was a "great" decision not to have conditional compilation in the language. It’s not the only technique but it would make it a lot easier. But you already almost answered. You would have three projects. Common, Free, Pay. The last two should be minimal, especially the Free that is only a glue even. I don’t officially answer because I wouldn’t know the specifics in the specific case.

  • Yes, in Java, I didn’t because I thought it was unnecessary. I really thought about what you said while writing the question, but as your new with Android Studio, I thought there could be an option, since this kind of division occurs a lot in the applications.

  • There are a number of options, but since I’m not familiar with the technology, I’ll refrain from indicating a few. There are some very crazy ones, but incredible as it seems adopted by several developers.

  • Okay, but your first comment has already given way, thank you!

  • 1

    Matthew, are you using Android Studio to develop your project? I say this because Gradle (which is used as Android Studio build tool) has a way to make this very easy. I am working out an answer with the details involved.

  • Yes @Wakim, Android Studio!

Show 1 more comment

1 answer

26


There is a pattern (not a Design Pattern in itself) Android/Gradle’s own to handle this. The prerequisite would be to use Android Studio and compile its apk using Gradle. Because it is Gradle that provides this functionality.

To handle generating two different apk’s, Gradle lets you define Build/Product Flavors.

Just as Build Types (release or debug), Build/Product Flavors are, as the name says, "flavors" (functionality/code, features, settings, etc...) that your app may have. The most common ones are: Free, Paid, Phone and Tablet (these last two being unnecessary depending on the type of customization you will do). You can give the name you want to a launder, has no limitation.

Correction: The combination of a Build Type with a Build Flavor generates a Build Variant. That would be used in the compilation of fact (this I explain better at the end).

And using Gradle it is possible to generate an apk for each combination of launder and build type available. More below I explain how to do this:

Build Configuration

A simple configuration of your file build.gradle would be:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "br.com.testegradleflavors"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    productFlavors {
        free {
            applicationId "be.tamere.testegradleflavors.free"
        }

        paid {
            applicationId "br.com.testegradleflavors"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
}

In this example, I define two Flavors: free and paid. Like the Google Play requires, each apk needs to have a unique ID. Soon each launder need to have a applicationId different because in the end it will generate a different apk.

No need and no need recommended change the package structure to match applicationId of each launder. That’s because Gradle can handle the "merge" of the Build Variant current.

Of course you can make this configuration more convoluted, like Build variables:

productFlavors {
        free {
            applicationId "be.tamere.testegradleflavors.free"
            buildConfigField "String", "VARIAVEL_ESTATICA", "\"free\""
        }

        paid {
            applicationId "br.com.testegradleflavors"
            buildConfigField "String", "VARIAVEL_ESTATICA", "\"pago\""
        }
    }

There are other settings, such as Multi-flavor Variants who would be Flavors of multiple levels, but this goes far beyond the scope of the question.

To access these Build variables in Java code:

String variavel = BuildConfig.VARIAVEL_ESTATICA;

Configuration of code/Resources

With respect to code, just follow this design structure (following the Gradle standard):

inserir a descrição da imagem aqui

In this image, illustrates my project that has three folders on the same hierarchical level: main with the code/Resources common to all Build Variants application possible (default on a currently created Gradle project), paid with the/Resources/files classes that are specific to the paid apk and the free with the classes/Resources/specific files for free apk.

When you modify the Build Variants (choosing a launder different), it visually disables the folders that are not being used. In the image for example appears the MainActivity with a red error symbol in the free folder, but this is because the folder was disabled when I chose the launder paid. When to modify the launder for free, the reverse will occur.

It is good not to use the same resource name (classes, xmls, files in general) between main and free/paid. Because the features of the more specific packages (free and paid) will overwrite the resources of the less specific (main).

When a launder is chosen for the build, it will consider all classes and Resources and will merge everything into the same apk, overwriting what you have repeated (prioritizing the launder). The files that exist in main but that there are no Flavors, will be included without problem in apk.

When building, simply choose the launder and the type. This can both be by command line:

gradlew assembleFreeRelease -- Build para o apk Free em modo Release
gradlew assemblePaidRelease -- Build para o apk Pago em modo Release

gradlew assembleFreeDebug -- Build para o apk Free em modo Debug

-- Demais configurações de build flavor e type

As for Graphical Interface: within Android Studio, just change the combobox option from Build Variants as in the image of the organization of the project.

References for better deepening:

  • Fantastic, amazing how something simple can be so useful, I just got a question, when you say that every launder have to have a different package, you’re referring to the applicationId or the file structure in the java folder?

  • 1

    Matthew, you are correct, the package structure does not change. Only the applicationId varies. Another thing I mixed was build variants and build type. I’ll correct that in response.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.