3

Is it possible to build apk with more than 1 product flavor?

For example: I have a Project with 3 flavors (App1 - App2 - App3).
and each app has its own configurations such as applicationId and so on.

and now I want to build different templates (different XML layouts), and the user should be able to switch from layout to another from inside the app.

My problem is the res folder will be huge and it will be hard to maintain, so I'm trying to find a way to separate the different layouts and keep it clean as much as possible.

And if it's possible to do so, then how do I intent or restart the app to the other flavors build?

Another thing I had in mind was to build all XML files in the main res and choose different qualifiers like when we do while creating different screen size (sm - larg - etc.. ) but i couldnt find anyway to add custom qualifiers.

My Gradle code is like this :

flavorDimensions "default"

    productFlavors {

        demo {
            applicationId "test.demo"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.demo.fileprovider"
            resValue "string", "bc", "com.demo"
            resValue "string", "bc_e", "extra_data.com.demo"
            resValue "string", "default_hostname", "demo.test.com"
            resValue "string", "default_username", "demo"
            resValue "string", "default_password", "demo"
        }
         AppOne {
            applicationId "test.AppOne"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.AppOne.fileprovider"
            resValue "string", "bc", "com.AppOne"
            resValue "string", "bc_e", "extra_data.com.AppOne "
            resValue "string", "default_hostname", "AppOne.test.com"
            resValue "string", "default_username", "AppOne"
            resValue "string", "default_password", "AppOne"
        }
          AppTwo {
            applicationId "test.AppTwo"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.AppTwo.fileprovider"
            resValue "string", "bc", "com.AppTwo"
            resValue "string", "bc_e", "extra_data.com.AppTwo"
            resValue "string", "default_hostname", "demoAppTwotest.com"
            resValue "string", "default_username", "AppTwo"
            resValue "string", "default_password", "AppTwo"
        }
}
Hossam Hassan
  • 795
  • 2
  • 13
  • 39
  • IMHO, If you just want to switch layout according to user input, you don't need to use product flavors. It can simply be achieved through some `if` statements. – theapache64 May 07 '19 at 00:30
  • im already using flavors for multiable apks, and i dont want to use if statements because that will be too much if i have 50 xml file and copy past them every time i want to make new template – Hossam Hassan May 07 '19 at 08:34
  • I think it's better to create an if statement rather than creating a module to just to switch a layout. – theapache64 May 07 '19 at 08:37
  • okay but than i will have a few problems: first if i have 2 different layouts (xml) files, first one will be called mainactivity.xml and 2nd template will be called mainactivity2 because and that will cause issue with java databinding. samething with activity styles. do u think any better solution ? – Hossam Hassan May 07 '19 at 08:54
  • i found something like this https://stackoverflow.com/questions/28232261/android-studio-gradle-product-flavors-define-custom-properties that you can add sub flavors but how do you call that in java ? – Hossam Hassan May 07 '19 at 09:15

2 Answers2

2

You cannot build an APK with multiple flavours, just as you cannot build one in both debug and release buildTypes. The selected flavour's config / resources gets pulled into the actual APK metadata / manifest, so cannot be modified at runtime.

You will need to include all of your content inside the res folder, but there are a few ways that may help make it easier to manage. I'd recommend the first 3 options, and the 4th if you have a very large number of code + layout files with different behaviour:

  1. Use Fragments to avoid most of your Java / Kotlin code needing to be duplicated.
  2. Include XML layouts instead of redefining everything each time to reuse common elements.
  3. Carefully name your files, for example template1_background, template2_background.
  4. Use multiple modules, one for each "template". You'll then have multiple sensible res folders.

I can see why flavours might have seemed like the solution, but since you need all flavours in one app, this approach is unfortunately not going to work. You'll likely find step #2 will remove almost all of the duplicate files, avoiding the issue entirely!

Jake Lee
  • 7,549
  • 8
  • 45
  • 86
  • use multple modules sounds good but the only issue i found with it is how to call it in java class, i mean in fragment/activity class how do i say if temp == temp_1 show xml from module_1 , and if i have java classes or styles in main src how do i call it inside the modules? as far as i know you can access what inside modules but modules cant access whats are on outside ? – Hossam Hassan May 08 '19 at 11:29
  • If your `app` module has a dependency on `module1`, `module2` etc, it can call anything (including layouts / java classes) from inside them. So the `app` module would control loading in the appropriate layouts / classes. That being said, steps 1+2 are worth trying first, as they're much easier (and good practice). – Jake Lee May 08 '19 at 11:42
  • 1
    I will try to find an easier solution first if there's none than it seems like I will go with the fragments option – Hossam Hassan May 12 '19 at 19:55
0

You can merge resources from different flavours using sourceSets command. SourceSet Allows you to congifure buildVariants resources folders for example you can configure your App2 flavour to include App2 res folder and App1 res folder. Example code:

sourceSets {


        App2Debug{
            res.srcDirs = ['src/App1/res', 'src/App2/res']

        }

    }
  • having multi resources with different xml names will cause as issue with databinding – Hossam Hassan May 19 '19 at 10:04
  • what do you mean problem with databaing? what problem? – OmerCohen1994 May 19 '19 at 14:23
  • for databinding you need to set your xml in java this way: private FragmentHomePageViewBinding binding; binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home_page_view, container, false); now if you have multi xml for the same java class u will have you will need rename 2nd databinding to be binding2 and binding 3 and so on, means there will be too much double in that class when u are setting text view or anything in the layout – Hossam Hassan May 19 '19 at 14:53
  • I know. Still dont understand the problems that caused by that? it doesnt know the layout? – OmerCohen1994 May 19 '19 at 14:56
  • the problem is if I have to set textview from API I will have to do it multi-able times for each binding, and that's not optimal and you can imagine with a class that has a lot of id in the UI then how big that class can get – Hossam Hassan May 19 '19 at 15:34