18

I need to create a demo flavor in android studio for an app. In my app level gradle file i have created another flavor called demo and the default flavor of full of course. It looks like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.example.uen229.myapplication"
        minSdkVersion 17
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    productFlavors {
        demo {
            applicationId "com.buildsystemexample.app.demo"
            versionName "1.0-demo"
        }
        full {
            applicationId "com.buildsystemexample.app.full"
            versionName "1.0-full"
        }
    }

}

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

and here is a image of my project structure in which I have created a demo flavor directory:

enter image description here

Now onto the issue. I have two classes called Hello.java. Both are in there respective flavors and print different things. I'll show you both files now:

import android.util.Log;

/** this is from demo flavor directory**/

public class Hello {

    Hello(){

        Log.v("","hello from demo");
    }

    public String getName();
        return "im from demo";

    };

}

And here is the other Hello:

package com.example.uen229.myapplication;

import android.util.Log;


/** this is from full or main flavor directory**/
public class Hello {


    Hello(){

        Log.v("", "hello from main");
    }

    public String getName(){

        return "im from main";

    };
}

notice how the first hello.java does not have package, even if i had a package the IDE wont compile. look at this photo:

enter image description here

Now finally lets look at mainActivity.java to see that when i switch build variants it only does a toast for "im from main" but i need it to print 'im from demo" if i use the demoDebug build variant. If i switch the build variant to demoDebug it still prints "im from main". can anyone help :

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Hello h = new Hello();
        Toast.makeText(this, h.getName(), Toast.LENGTH_LONG).show();

    }
}

UPDATE

From stackoverflow it says:

If you want to have a different version of the same class in the two flavor you'll need to create it in both flavors.

src/flavor1/java/com/foo/A.java

src/flavor2/java/com/foo/A.java

And then your code in src/main/java can do:

import com.foo.A

depending on the flavor selected, the right version of com.foo.A is used.

This is what I want to accomplish with the Hello class

Sufian
  • 5,997
  • 14
  • 60
  • 111
j2emanue
  • 51,417
  • 46
  • 239
  • 380

3 Answers3

18

I think you can't have same class in main flavor and your other flavor. you should just create another flavor, then move your Hello class from main flavor to that new flavor. this rule is just for .java files. I mean you can have an xml file in main flavor and another version in your custom flavor but you can't do this with java files.

here is a useful link with further explanation.

Community
  • 1
  • 1
Mohammad Rahchamani
  • 4,406
  • 1
  • 22
  • 35
  • looks like you can override class name if you remove it from main just like you said. but you have to maintain the same package name. Excellent. but doesn't that mean i cant build fullRelease now ? its just going to be there to store common things but i could never run it right because it would be missing a class(s) ? – j2emanue Jun 24 '15 at 16:00
  • I think there is no difference in flavor's package names, just there path is different and when you build your project, classes in different paths merged together. so you can build your project without any problem but if there is a function `a` in class `X` in flavor `one` and function `b` in class `X` in flavor `two`, and you have just one main class in main flavor, you can't call those functions because when you are building flavor `one`, there is no function `b` and vice versa. – Mohammad Rahchamani Jun 25 '15 at 05:57
4

I would advice to create 3 source sets:

  • main - which would contain common classes
  • demo - contains demo specific classes
  • pro - contains classes for pro versions

and declare them using:

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src/main/java']
        res.srcDirs = ['src/main/res']
        assets.srcDirs = ['src/main/assets']
    }
    pro {
        manifest.srcFile 'src/pro/AndroidManifestPro.xml'
        java.srcDirs = ['src/main/java', 'src/pro/java']
    }
    demo {
        manifest.srcFile 'src/oldlite/AndroidManifestDemo.xml'
        java.srcDirs = ['src/main/java', 'src/demo/java']        
    }
}

P.S. not really sure about syntax of java.srcDirs content - please double check yourself

Barmaley
  • 16,009
  • 17
  • 68
  • 139
  • 3
    what i want to do is override classes not make specific classes. So if i have the class Hello in main i want to override it in the demo flavor to do another behavior. Can overriding be done like this ? – j2emanue Jun 24 '15 at 15:13
  • Nope you can't - I'd advice to use another Hello.java in different package – Barmaley Jun 24 '15 at 17:23
  • We have created the same product flavour, but we are not able to open common flavour Activity from different flavour. – Chetan Chaudhari Jan 08 '20 at 13:16
2

I was able to override classes but the key was not to include the class in my main folder.

So the fullDebug (i.e. main folder) build variant will never get run. Always run a flavor and not the main folder. The main folder will just be used to keep common things in it.

In my case I had a demo for USA and another country (demo and demo_us)and I needed two flavors. I'll always build for either of the two and won't build main.

enter image description here

From the image you can see I made all my package names to be the same: like com.example.******.myapplication. Since they all have the same package name in the MainActivity you just import Hello.java with that package name and it will pick the right variant at build time.

For resources it looks like it's different and it will override naturally but java class files have to do this way.

j2emanue
  • 51,417
  • 46
  • 239
  • 380
  • thank you for your answer, this is exactly what I was looking for. What if I wanted to extend an existing Activity java code (MyActivity.java) but not copy and paste the same activity in a different flavor and add the specific edits? My Activity contains a lot of code and I would like to keep it in common but only extends few new functionalities in a specific flavor. – Alberto M Jan 22 '16 at 16:13
  • not with the flavors but with the configurations you can. in build.gradle you have two configurations most likely, debug and release. You can create folders just like you did flavors in the directory structure. One for "debug" and one for "release". so you can copy just the Myactivity.java to debug folder and one to release folder. then when you run flavor1Debug it would use the debug version of MyActivity.java. Otherwise, you have to put it in main src directory if you want it common. – j2emanue Jan 22 '16 at 18:27
  • We have created the same product flavour, but we are not able to open common flavour Activity from different flavour – Chetan Chaudhari Jan 08 '20 at 13:16