使用Build Flavors-构建源文件夹并正确build.gradle


166

请注意:答案在Xavier的答案之后进行了编辑

我正在为Android Studio中的一个相同Application项目使用不同的Build Flavors。但是,我似乎在配置它以使其正常工作方面花费了很多时间。

脚步:

  1. 创建一个新的Android Studio项目,名为“测试”。
  2. 打开build.gradle *并添加以下行:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
  3. 重新启动Android Studio之后,我现在在Build Variants部分下看到4个构建变体。表示到目前为止,我们已经成功设置了产品口味。**
  4. flavour1创建了一个新的Source文件夹;但是,我不确定我是否做对了。这是我的做法:

    • 请记住,我为此项目的软件包名称是: com.foo.test
    • 右键单击src文件夹,对于flavor1,我实际上在浏览器中以结构为的方式创建了各个文件夹src/flavor1/java/com/foo/test/MainActivity.java
    • 上面的方法运行良好,因为'java'文件夹为蓝色,这意味着IDE知道其处于活动状态的源目录。此外,该包是自动创建的。尽管如此,对于重复的类,我仍会收到警告。在这里查看截图。
    • 对于flavour2,我尝试手动创建程序包,但flavour2的'src'文件夹似乎不是蓝色,因此右键单击时这些选项有所不同,并且'New Package'不可用。在此处查看图片。
    • 请注意,对于flavor1,我还创建了一个“ res”目录,该目录的确变为蓝色,但是尽管如此,在我想使用其他目录的情况下,它也无法创建Android Resource文件或Andorid资源目录重新调配不同的口味。

难道我做错了什么?还是我错过了什么?让我知道您是否需要更多信息。

*我的项目似乎有两个 build.gradle文件。一个位于项目文件夹(\ GradleTest)的根目录下,此为空。第二个位于\ GradleTest子文件夹的根目录下,也称为“ GradleTest”(GradleTest-GradleTest),这是打开时已经有代码的那个。因此,那是我编辑的那个。

**我检查gradle这个设置,显然使用自动导入已启用。尽管如此,对build.gradle文件进行更改并不会自动更新构建变体。注意:我也尝试过使用Build-Rebuild Project和/或Build-Make Project,不要忙。我仍然必须关闭项目,然后重新打开以使更改生效。


请注意,applicationId现在支持而不是packageName
Hamzeh Soboh's

Answers:


220

如果您在Studio偏好设置中进入了Gradle部分,则可以为您的项目启用自动导入(我们将在默认情况下启用此功能)。这样,Studio每次进行编辑时都会重新导入build.gradle。

创建风味并不意味着您将为其使用自定义代码,因此我们不会创建文件夹。您确实需要自己创建它们。

如果您看我的IO演讲,您将看到我们如何将风味和构建类型中的值混合在一起以创建变体。

对于Java源:

src/main/java
src/flavor1/java
src/debug/java

全部用于创建单个输出。这意味着他们不能定义相同的类。

如果要在两种口味中使用同一类的不同版本,则需要在两种口味中创建它。

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

然后您在src / main / java中的代码就可以

import com.foo.A

根据选择的口味,使用正确版本的com.foo.A。

这也意味着两个版本的A必须具有相同的API(至少在src / main / java / ...

编辑以匹配修改后的问题

另外,将相同的A类仅放置在互斥的源文件夹中也很重要。在这种情况下,永远不会一起选择src / flavor1 / java和src / flavor2 / java,但同时选择main和flavour1。

如果要提供具有不同风格的活动的不同版本,请不要将其放在src / main / java中。

请注意,如果您有3种口味,而只希望为flavour1自定义一个口味,而flavour2和flavour3共享相同的活动,则可以为其他两个活动创建一个公共源文件夹。您可以完全灵活地创建新的源文件夹并配置源集以使用它们。

关于您的其他观点:

通常,第二个口味来源文件夹不是蓝色。您需要切换到第二种样式来启用它,然后才能在其中创建包和类。在此之前,Studio不会将其视为源文件夹。我们希望将来会对此进行改进,以使IDE知道那些无效的源文件夹。

我认为您不能在res文件夹中创建资源文件也是正常的。菜单系统尚未更新以处理所有这些额外的资源文件夹。稍后再说。


1
我在回答的末尾添加了一些新元素,但是重复是有意义的。src / main / java和src / flavor1 / java中的类不能相同,因为选择flavour1时要使用这两个类。在我的答案中,请注意如何将相同的类仅放在flavor1 / java和flavor2 / java中,因为它们是互斥的,并且从未一起启用。
Xavier Ducrohet

嗨Xavier,您能否详细说明如何在口味中使用其他版本的活动?我有一个测试项目,我想使用MainActivity的不同版本,但是在两个APK(flavor1和flavour2)中都只有main / java版本。当我不将MainActivity放入main / java时,启动时应用程序崩溃。
JensJensen 2014年

@XavierDucrohet如何根据风味来拥有不同的资源和不同的代码,但是将它们放在不同的模块中,这样我们就可以基于风味来包含一个模块或另一个模块,而不必在同一根项目中混合代码和资源。支持吗?
Valerio Santinelli 2014年

3
@ValerioSantinelli您可以执行每种口味的依赖关系。使用flavorCompile ...
Xavier Ducrohet 2014年

@XavierDucrohet我尝试了您的建议,但未按预期工作。您可以在那里查看我的项目的结构:stackoverflow.com/q/24410995/443136
Valerio Santinelli,2014年

19

Android上的“产品口味”

有时有人问我如何使用不同的主机,图标甚至程序包名称,具体取决于同一应用程序的不同版本。

这样做有很多原因,而且有一种简便的方法:产品调味剂。

您可以在build.gradle脚本中定义我之前描述的这类内容。

产品口味 本文的一部分是关于产品口味的书面思考,那么,它们是什么?关于Android文档:

产品风格定义由项目构建的应用程序的定制版本。一个项目可以具有改变生成的应用程序的不同风格。

您如何定义它们?您必须在build.gradle上编写要定义的风味:

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

现在,我们将拥有两种不同风格的应用程序。您也可以在Build Variants选项卡中的Android Studio上对其进行检查

构建变体

多个包装名称

如果您想在手机上安装一个处于开发状态而另一个处于生产状态的应用程序,该怎么办。如您所知,您只能安装一个具有相同程序包名称的应用程序(如果您尝试安装一些与手机上安装的APK相同的新APK,它将尝试更新它)。

唯一要做的就是在每种产品口味上定义它:

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
        }
        prod {
            applicationId "zuul.com.android"
        }
    }
}

根据口味将请求发送到多个主机与以前一样,您必须在产品口味配置字段中包含一些参数。

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
            buildConfigField 'String', 'HOST', '"http://192.168.1.34:3000"'

        }

        prod {
            applicationId "zuul.com.android"
               buildConfigField 'String', 'HOST', '"http://api.zuul.com"'

        }
    }
}

举例来说,我们将尝试向您展示如何将其与Retrofit集成在一起,以将请求发送到适当的服务器,而无需处理您指向的服务器以及基于风味的服务器。在这种情况下,这是Zuul android应用的摘录:

public class RetrofitModule {

    public ZuulService getRestAdapter() {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(BuildConfig.HOST)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        return restAdapter.create(ZuulService.class);
    }

}

如您所见,您只需要使用BuildConfigclass来访问刚刚定义的变量。

通过代码可获得的任何变量HOST变量不是您可以在代码中公开的唯一变量。您可以随心所欲地做到这一点:

prod {  
    applicationId "zuul.com.android"
    buildConfigField 'String', 'HOST', '"http://api.zuul.com"'
    buildConfigField 'String', 'FLAVOR', '"prod"'
    buildConfigField "boolean", "REPORT_CRASHES", "true"
}

您可以按以下方式访问它们:

BuildConfig.HOST  
BuildConfig.FLAVOR  
BuildConfig.REPORT_CRASHES  

每种口味具有不同的图标如果您希望每种口味具有不同的图标,则可以直观地检测到要打开的图标(也可以用名称来实现...但是它不能容纳空间!),您只需为每种口味定义新的目录结构。

在我刚刚使用的示例中,有两种口味:devel和prod。然后,我们可以定义两个新的目录结构,以便可以定义所需的资源:

结构体

这适用于其他类型的资源,例如strings.xml, integers.xml, arrays.xml等等。

配置签名设置

要使用Gradle构建配置为发布构建类型手动配置签名配置,请执行以下操作:

1.创建密钥库。密钥库是一个二进制文件,其中包含一组私钥。您必须将密钥库保存在安全的地方。2.创建一个私钥。私钥代表要与应用程序标识的实体,例如个人或公司。3.将签名配置添加到模块级别的build.gradle文件中:

android {
...
defaultConfig {...}
signingConfigs {
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}
buildTypes {
    release {
        ...
        signingConfig signingConfigs.release
    }
}

}

生成签名的APK:

要生成签名的APK,请从主菜单中选择“构建”>“生成签名的APK”。现在,使用您的发布密钥对app / build / apk / app-release.apk中的软件包进行了签名。

参考:https : //developer.android.com/studio/build/build-variants.html#signing,http : //blog.brainattica.com/how-to-work-with-flavors-on-android/



7

似乎您需要在中添加新的样式后重新加载项目build.gradle。之后,您将在Build Variants视图中看到4个build Variants(您可以从窗口的左边缘访问它)。

关于其他源目录,似乎您需要手动创建它们:src/flavor1/javasrc/flavor2/java。你会看到,在“构建变量”视图改变味道会改变当前活动的源目录(目录为蓝色,当它是一个活跃的源目录

最后,“ gradle将为您的新口味创建新的sourceSets”意味着gradle将创建对象android.sourceSets.flavor1android.sourceSets.flavor2并且您可以在build.gradle脚本中使用它们。但是这些对象是动态创建的,因此,您在build.gradle(我建议您阅读以下内容时看不到它们:http : //www.gradle.org/docs/current/userguide/tutorial_using_tasks.html尤其是6.6:它解释了创建动态任务。gradle脚本是一个groovy脚本,所以我建议您也熟悉groovy)


2
我认为导入说明是“ Build Variants视图”,我没有注意到。
克里斯·詹金斯(Chris.Jenkins),

2

当我将项目迁移到Gradle时,我遇到了同样的问题。问题是该构建找不到正确的资源文件夹。我通过在build.gradle的android元素下添加此代码来解决此问题:

sourceSets {
        main {
            res.srcDirs = ['myProject/res']
        }
    }

0

重要的一件事使我受阻了很长时间,那就是需要与包装匹配的风味名称,而不是gradle中的风味定义中定义的包装。例如:

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

将匹配

productFlavors {
  flavor1 {
    packageName 'com.android.studio.test.foobar'
  }
}

src/foobar/java/com/foo/A.java 将不会用于flavor1构建。


0

在gradle中:

对于构建类型,您只需要:

buildTypes {
   release{
    //proguard, signing etc.
   }
   debug {
    //development
   }
  }
}

然后为风味添加所需的风味

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.