0

Ok I am not sure if this has been asked before. But I am struggling with the core concepts of Build variants, flavors and the way they are structured.

I have a an app on Google play so I am gonna use it for reference. My app Nexus Notes is a one build. I was thinking about turning it into a paid/free version along with some future apps.

When I go into the project view add the flavors and deminsions in the Gradle. I then add the resources to match the main resource. My issue is when I have the layouts and everything setup, how do I have them called in the code?

I followed Androids documentation and I don't understand the whole picture. To me they skipped a step somewhere. Do I need to add some other code other than just in the project. Like an override resource function.

I have my release, free and paid build. For testing purposes I chose the PaidDebug variant but my designs don't show. It's just what's on the main.

I am trying to accomplish a one app build variant, instead of having two apps on Google Play one free and one paid.

I understand how to add it, I just don't understand how to use it. I know Google frowns on duplicate apps, so I am just trying to clean my structure up so it's a unified app and not two separate apps.

If there is any documentation that is a complete step by step process so I can learn the correct way of adding build variants and flavors I am greatly appreciated.

I will add my code shortly in an update. Currently I am away from my code.

Camp Nerd
  • 327
  • 1
  • 11
  • Why do you need flavors if you are building a single variant? For other stores? – Tenfour04 Nov 03 '22 at 12:22
  • @Tenfour04 some of my apps is a single variant, but I have a few upcoming apps that is a free/paid. So my issue is having one app free and another app paid it would wipe the data by two separate apps. My app Nexus Notes uses room DB for the "free version" if I have a paid version it would have more features and cloud syncing with firebase. So I am trying to build it as a flavor instead of two apps. I have not fully decided if this is the correct option yet – Camp Nerd Nov 03 '22 at 12:26
  • @Tenfour04 I can use the persistent option in room and retain the local DB on uninstall and the data be there when reinstalled. However, if you purchase the premium that DB will be over written if I had two apps. I was thinking one app the paid would use room and firebase. So the premium would not over write the room DB. I have been struggling with this concept for some time now on what's the best practice – Camp Nerd Nov 03 '22 at 12:29

1 Answers1

2

My typical strategy is to create a build config Boolean field for whether premium features are enabled. This can be used to turn off features in your Kotlin/Java code so you can keep everything in one module. In Gradle, for each variant you can specify alternate resource directories that will override whatever has the same ID in the default res directory. You can also specify extra manifest files that add entries to the base manifest.

I keep my base res directory with all the assets for the premium version, and put alternate free version variants of the relevant resources in res-free. And each variant can have its own extra manifest for declaring Activities/Services/Receivers that are unique to that version.

I use BuildConfig.IS_PREMIUM, set up as shown below, to turn features or ads on and off.

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
        jniLibs.srcDirs = ['libs']
    }

    free {
        manifest.srcFile 'AndroidManifest-free.xml' // extra manifest file in same directory as original
        res.srcDirs = ['resFree'] // extra resource directory in same directory as res
    }

    premium {
        manifest.srcFile 'AndroidManifest-premium.xml'
    }

}

flavorDimensions 'content'

productFlavors {

    free {
        dimension "content"
        applicationId "com.me.mypackage.free"
        buildConfigField "boolean", "IS_PREMIUM", "false"
    }

    premium {
        dimension "content"
        applicationId "com.me.mypackage.premium"
        buildConfigField "boolean", "IS_PREMIUM", "true"
    }

}
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • I now see my issue.. the Android documentation did not specify the sourceSet part. That's the only thing missing from my Gradle. However Android documentation did mention it it was very brief and they did not say where to put it. So I will add that in my Gradle and get back to you. – Camp Nerd Nov 03 '22 at 12:45