Android Studio构建flavors - 如何在不同flavor中拥有相同的源文件

22

我需要在 Android Studio 中为一个应用创建一个演示版本。在我的应用级别的 gradle 文件中,我已经创建了另一个名为“demo”的版本,而默认版本当然是完整版。它看起来像这样:

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'
}

以下是我创建了一个演示 flavor 目录的项目结构图片:

在此输入图片描述

现在来看问题。 我有两个名为 Hello.java 的类。 它们分别位于它们各自的 flavor 中,打印不同的内容。 现在我将展示这两个文件:

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";

    };

}

这里是另一个问候:

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";

    };
}

请注意,第一个hello.java文件没有包名,即使我添加了包名,IDE也不会编译它。请看这张照片:

图片描述

现在让我们最后看一下mainActivity.java文件,当我切换构建变体时,它只显示“来自主要”,但我需要它在使用demoDebug构建变体时打印“来自demo”。如果我将构建变体切换到demoDebug,它仍然会打印“来自主要”。有人能帮忙吗:

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();

    }
}

更新

根据stackoverflow上的说法:

如果您想在两个版本中拥有同一类的不同版本,则需要在两个版本中都创建它。

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

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

然后,您在 src/main/java 中的代码可以执行:

import com.foo.A

根据所选的版本,将使用正确的com.foo.A版本。

这就是我想通过Hello类实现的目标。

3个回答

21

我认为在主要版本和其他版本中不能有相同的类。你应该创建另一个版本,然后将Hello类从主版本移动到新版本。这个规则只适用于.java文件。我的意思是你可以在主版本中有一个xml文件,在自定义版本中有另一个版本,但是你不能在Java文件中这样做。

这里是一个有关此问题的有用链接。


看起来你可以像你说的那样从主要代码中删除类名并覆盖它。但是你必须保持相同的包名。太好了。但这不意味着我现在不能构建fullRelease吗?它只是用来存储常见的东西,但我永远无法运行它,因为它会缺少一个或多个类吗? - j2emanue
我认为口味包的名称没有区别,只是它们的路径不同,当您构建项目时,不同路径中的类会合并在一起。因此,您可以毫无问题地构建项目,但是如果在口味“one”中的类“X”中有函数“a”,并且在口味“two”中的类“X”中有函数“b”,而且您只有一个主要类在主要口味中,您无法调用这些函数,因为在构建口味“one”时没有函数“b”,反之亦然。 - Mohammad Rahchamani

4
我建议创建3个源集:
  • main - 包含公共类
  • demo - 包含演示特定的类
  • pro - 包含专业版本的类
并使用以下方法声明它们:
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']        
    }
}

附注:关于java.srcDirs内容的语法不是很确定,请自行仔细检查。


3
我的意图是覆盖类而不是创建特定的类。因此,如果我在主函数中有一个名为Hello的类,我想要在演示版本中重写它以执行其他行为。这样能否进行覆盖操作? - j2emanue
不行,你不能这样做 - 我建议在不同的包中使用另一个Hello.java。 - Barmaley
我们已经创建了相同的产品版本,但是我们无法从不同的版本打开公共版本的Activity。 - Chetan Chaudhari

3
我能够覆盖类,但关键是不要在我的主文件夹中包含该类。
因此,fullDebug(即主文件夹)构建变体永远不会运行。始终运行口味而不是主文件夹。主文件夹只用来保存公共内容。
在我的情况下,我有一个美国和另一个国家的演示(demo和demo_us),我需要两种口味。我将始终为其中之一构建,并且不会构建主要内容。
从图像中可以看出,我使所有包名称都相同:例如com.example.******.myapplication。由于它们在MainActivity中具有相同的包名称,因此您只需使用该包名称导入Hello.java,它将在构建时选择正确的变体。
对于资源,似乎不同,并且会自然覆盖,但Java类文件必须以这种方式处理。

谢谢您的回答,这正是我想要的。如果我想要扩展现有的Activity Java代码(MyActivity.java),而不是复制并粘贴相同的Activity到不同的风味中并添加特定的编辑,该怎么办?我的Activity包含很多代码,我想保持它的通用性,但只在特定风味中扩展一些新功能。 - Alberto M
在build.gradle中,您很可能有两个配置,即debug和release。您可以像在目录结构中创建flavors一样创建文件夹。一个是“debug”,另一个是“release”。这样,您就可以将Myactivity.java复制到debug文件夹和release文件夹中。然后,当您运行flavor1Debug时,它将使用MyActivity.java的调试版本。否则,如果您想要它通用,则必须将其放在主src目录中。 - j2emanue
我们已经创建了相同的产品风味,但是我们无法从不同风味打开公共风味活动。 - Chetan Chaudhari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接