1

I have a class UserManager which handles creation and user sessions:

src/main/java/com/myapp/UserManager.java:

public class UserManager {

    public UserManager(){
        if(BuildConfig.DEBUG){
           createAndLogin("dummy", "dummy");
        }
    }

    public void createAndLogin(String username, String password){
        // Create and login logic
    }

    /* Some more methods */

}

As you can see, when in debug mode, I want to automatically login, so I don't need to do that manually each time I push the app to the development device.


I am wondering if I can do this more efficiently. I've tried to create a debug folder, and copy the class. The new setup would be:

src/main/java/com/myapp/UserManager.java:

public class UserManager {

    public void createAndLogin(String username, String password){
        // Create and login logic
    }

    /* Some more methods */

}

And:

src/debug/java/com/myapp/UserManager.java:

public class UserManager {

    public UserManager(){
       createAndLogin("dummy", "dummy");
    }

    public void createAndLogin(String username, String password){
        // Create and login logic
    }

    /* Some more methods */

}

Unfortunately, this is not allowed, as it complains about a duplicate class.


As mentioned here, you need productFlavors to accomplish this. The setup in build.gradle would be:

buildTypes {
    debug {
        debuggable true
        signingConfig signingConfigs.debug
    }
    release {
        debuggable false
        signingConfig signingConfigs.release
    }
}

productFlavors  {
    dev { }
    prod { }
}

Now I have moved the two classes to src/prod/..., and src/dev/..., and deleted the class from src/main/....

This works, but I'm still not happy. I require a lot of duplicate code, and I'm not sure I'm using the productFlavors as they should be used.

TL;DR

How can I use productFlavors or something similar to easily login in development builds?

Community
  • 1
  • 1
nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • 1
    Don't use flavors, and have a version of `UserManager` in src/debug and another one in src/release, and none in src/main? If both of them want to share a lot of code, then create a common base class for both and put it in src/main. Having said all that, I'm not sure it's easier than your first approach of just having a conditional on BuildConfig.DEBUG -- that's IMHO easier to maintain than multiple versions of the class. – Scott Barta Aug 14 '14 at 18:33
  • Hey @ScottBarta, thanks! That would still require me to duplicate code, right? Perhaps I should create a subclass in both `debug` and `release`, were the one in `release` is empty, and the one in `debug` contains only the constructor? – nhaarman Aug 14 '14 at 18:36
  • @ScottBarta Honestly, I forgot that I could use the `release` folder, so that's a big help! – nhaarman Aug 14 '14 at 18:37
  • Yeah, there's duplicate code, but it seems like you're leaning toward an approach that uses duplicate code -- the approach that doesn't duplicate is the `if (BuildConfig.DEBUG)` one. – Scott Barta Aug 14 '14 at 18:38
  • Cool, I wrote it up as a more descriptive answer. – Scott Barta Aug 14 '14 at 18:43

1 Answers1

3

In my opinion, your first approach of doing:

    if(BuildConfig.DEBUG){
       createAndLogin("dummy", "dummy");
    }

isn't that bad. It keeps all the code in one place. Having said that, your second approach of putting code in src/debug is close, and you don't need to use product flavors at all to go that way. Do this:

  • Put the createAndLogin version of UserManager in src/debug
  • Put the normal version of UserManager in src/release
  • Don't put anything in src/main.

If both versions of that class have a lot of common logic, then you could make each of them inherit from a common base class that you do put in src/main.

One disadvantage to this approach is that at present, Android Studio isn't smart enough to have code that's in flavors or build types other than the current one participate in important things like refactoring. What that means is that if you're currently working on the debug build type and you refactor UserManager by, say, moving it to a different package, it won't refactor the copy in your release build type, and that will be orphaned until you go fix it up.

Scott Barta
  • 79,344
  • 24
  • 180
  • 163
  • Thanks! Obviously, in real life there are some more configurations I'd like to provide in debug mode, so the thought of having a separate debug folder with these configurations sounds like a nice solution. I will struggle with this, and see if it's worth the trouble. Something like [Laravel's environment configurations‌​](http://laravel.com/docs/configuration#environment-configuration). – nhaarman Aug 14 '14 at 18:43
  • 1
    Yeah having it be smart about that sort of thing has been on our wish list for a long time, but unfortunately, it's quite difficult to implement. – Scott Barta Aug 14 '14 at 18:45