我如何将 2 个类似的项目与 Android Build Variant 结合起来?

How can I combine 2 Similar Projects With Android Build Variant?

我们确实有 2 个类似的应用程序项目。第一个是针对我国的,第二个是针对欧盟的。他们是 %90 相同可能更多。我们确实想将这两个项目合并为一个,并使用构建变体在它们之间切换。那可能吗?如果是,我该怎么做?

主要项目

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

欧盟项目

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.EuInactive);
            ImageView.setContentDescription(getString(R.string.EUpassive));
            presenter.sendCommand();
            isEnabled = false;
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.EUactive));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

例如,某些可绘制对象在 EU 项目中有所不同

- 或 -

主要项目

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
            DoSomething();
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

欧盟项目

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
            DoSomethingElse();
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

在这个例子中,我们确实添加了不同的行,其他都是相似的。

有近千个这样的差异,近五百个完全相同的类和两百个新的类。

总而言之,如何在一个项目中管理这两个具有构建变体的项目?

编辑 2:我已经尝试了这些步骤。

  1. 执行维度
  2. 实施风味
  3. 为 eu 项目创建了 res,asset,java 文件
  4. 在 gradle 中为欧盟项目创建了 sourceSet

现在构建变体看起来像这样 mainDevDebug、EuDevDebug、...等 main ...... ones 工作正常但我对 Eu 有错误...... ones

重建或 运行 应用程序时出现错误消息:

Could not determine the dependencies of task ':app:compileEuTestDebugJavaWithJavac'.
> Could not resolve all task dependencies for configuration ':app:EuTestDebugCompileClasspath'.
   > Could not resolve project :com.xx.core.main.core.
     Required by:
         project :app
      > No matching configuration of project :com.xx.core.main.core was found. The consumer was configured to find an API of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug', attribute 'project' with value 'Eu', attribute 'default' with value 'Test', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' but:
          - None of the consumable configurations have attributes.

根据您发布的代码和评论,我相信您能够通过产品口味 read more here.

实现您想要的效果

在您的 APP 级别 build.gradle 中,您会做这样的事情:

android {  
    flavorDimensions 'default'
    productFlavors {

        foo{
            dimension 'default'
        }

        bar{
            dimension 'default'
        }

    }
}

这将为您定义两种不同的产品口味,特别是 foobar。在进行 gradle 同步后,您会看到这些现在可以作为构建变体使用。

接下来您要做的是创建一个与此类似的文件夹结构:

bar 创建一个文件夹,为 foo 创建一个文件夹,并为 main 创建一个文件夹,每个文件夹中的包签名与您的主要结构使用的相匹配。如果您有不同的图像资源,请确保它们位于此处的适当文件夹中。如果您正在努力创建特定类型的 file/folder,我建议您将其复制过来。

main 中的所有内容都将在两种类型的应用程序中使用,因此所有相同的逻辑都将保留在那里。所有可能不同的内容都将驻留在 barfoo 的文件夹中。在我的例子中,一个简单的 class 叫做 Example:

class Example {

    fun giveValue(context: Context): String {
        return context.getString(R.string.value)
    }
}

这两个 class 的实现在两个文件夹中完全相同,尽管您的可能(并且将会)完全不同。

您还会看到我已将 strings.xml 添加到我的产品风格中(在您的情况下,也许这也是图像资源),我添加了以下字符串:

<resources>
    <string name="value">from bar</string>
</resources>

进入 bar 目录下的 strings.xml 和

<resources>
    <string name="value">from foo</string>
</resources>

进入foo目录下的strings.xml

my Example class 因此只是 returns 无论这个值是什么 基于构建变体

就是这样。

在我的主要 activity:

  val result = Example().giveValue(this)
        Log.v("testing", result) 

因此,根据我使用的构建变体(fooDebug or barDebug),输出会有所不同。