1

My project structure look like below

+ src
        + main // this is my common code
            + java 
                - LoginScreen // depending on condition launch screen from flavor1 or flavor2 
            + res
        + flavor1
            + java
            + res
        + flavor2
            + java
            + res

I have Login class in main/src depending on condition, have to launch the screen from flavor1 or flavor2.

For example:

class LoginScreen{
......

    if(true){
        // launch ScreenUser from Flavor1 reset of screen flows from falvour1
    }else{
       // launch ScreenOTP from Flavor2 reset of screen flows from falvour2
    }
}

In this case, if I make build for flavor1 it is showing an error for falvor2 class and vice versa.

Both flavors has different applicationId like applicationIdSuffix ".flavor1"

Is this possible? If not how can I achieve this?

halfer
  • 19,824
  • 17
  • 99
  • 186
N J
  • 27,217
  • 13
  • 76
  • 96
  • if you have to launch say UserScreen, put UserScreen.java in both flavors and put respective implementations in there. Then just call it from your LoginScreen – gitter Jan 05 '17 at 11:10
  • Why don't you identify that by using application Id? That's unique – M D Jan 05 '17 at 11:11
  • Are you trying to open ClassA in flavor1 and classB in flavor2 if true and vice versa? In that case, you should keep both classes in main and rather have a different class in both flavors which decides which screen to launch based on the value you provide (i.e. what that if block does). – gitter Jan 05 '17 at 11:49

2 Answers2

5

When I've done this sort of thing I've used interfaces and dependency injection (I use dagger). Something like:

public interface LoginBehaviour {

    void goToNextScreen(Context context);
}

Then define an implementation in each flavour which contains the code to launch the next screen. Something like:

public class FlavourOneLoginBehaviour implements LoginBehaviour {

    @Override
    public void goToNextScreen(Context context) {
        context.startActivity(new Intent(context, ScreenUser.class));
    }

}

And:

public class FlavourTwoLoginBehaviour implements LoginBehaviour {

    @Override
    public void goToNextScreen(Context context) {
        context.startActivity(new Intent(context, ScreenOTP.class));
    }

}

The you need to set up your dependency injection container in each flavour so that it references the local implementation (this will vary depending on which framework you use). After you've done that, you can use the container in the main project to get the correct implementation of the LoginBehaviour interface at run time, and you can call goToNextScreen on it to do your navigation. Dependency injection is a really handy way to ensure that you can swap out parts of your code without having to do major refactoring, and helps a lot with reuse and flexibility. Hope that helps!

GeordieMatt
  • 1,236
  • 1
  • 9
  • 7
  • Thanks buddy, I have solved it by using implicit intent – N J Jan 05 '17 at 12:54
  • @GeordieMatt, As far as I have understood, the interface is placed in the main flavor and each implementation in respective flavor. But, I am not able to know how DI works for to reference the local implementation. Would you share the code snippet of setting up dependency injection container in each flavor? – Charan Feb 28 '18 at 13:20
  • @Charan Your best bet for that is the documentation for your DI framework. I'd recommend Dagger for Android apps (the link is in the answer). – GeordieMatt Mar 02 '18 at 16:41
1

One of the possibilities to do that, if you want to have only one class with the if that check your buildType/productFlavor - you can set the value of BuildConfig field in both buildTypes/productFlavors by adding:

productFlavors {
  flavor1 {
    buildConfigField "String", "BUILD_FLAVOR", "Flavor1"
  }
  flavor2 {
    buildConfigField "String", "BUILD_FLAVOR", "Flavor2"
  }
}

And then you can use it in the code:

class LoginScreen {
......

  switch(BuildConfig.BUILD_FLAVOR) {
    case "Flavor1":
      // launch ScreenUser from Flavor1
      break;
    case "Flavor2":
      // launch ScreenOTP from Flavor2
      break;
  }
}

Hope, I've helped. Good luck!

NonGrate
  • 862
  • 9
  • 22
  • Tried this as well but it's showing the compile error on import for ScreenUser if I made build with flavour2 – N J Jan 05 '17 at 11:34
  • Could you publish here the compile error details? Unfortunately, I cannot even guess, what problem can be there. Thanks! – NonGrate Jan 05 '17 at 11:38
  • It's giving me an error on import Activity from flavro1 import statement. `Error:(17, 55) error: package com.mypackage.views.product_selection does not exist` as this activity is from another flavor – N J Jan 05 '17 at 11:41
  • 1
    If you want to use different classes for different flavors - you should either to have LoginScreen in the flavors' directories and to be implemented regarding each flavor seaprately, or you can have all classes for both flavors in the main directory, and use my approach with `switch` or `ifs` – NonGrate Jan 05 '17 at 11:54
  • Thanks buddy, I have solved it by using implicit intent – N J Jan 05 '17 at 12:54