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

时间:2013-05-24 14:11:45

标签: android intellij-idea gradle android-studio

请注意:在Xavier的答案

之后编辑的答案

我正在尝试在Android Studio中为同一个应用项目使用不同的Build Flavors。但是,我似乎很难配置它以正常工作。

步骤:

  1. 创建一个名为' Test'的新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 build variants 。这意味着我们迄今为止在成功提供产品口味方面取得了成功。 **
  4. flavor1 创建了一个新的Source文件夹;但是,我不确定我是否以正确的方式做到这一点。以下是我的表现方式:

    • 请注意,此项目的我的包名称为:com.foo.test
    • 右键单击src文件夹,对于flavor1,我实际上在浏览器中创建了单个文件夹,结构为src/flavor1/java/com/foo/test/MainActivity.java
    • 以上工作得很好,因为' java'文件夹位于蓝色中,这意味着IDE知道它是一个活动的源目录。此外,包是自动创建的。尽管如此,我发现了重复课程的警告。 See screenshot here.
    • 对于flavor2,我尝试手动创建包,但是' src' flavor2的文件夹似乎不是蓝色,因此右键单击时选项会有所不同,并且'新包装'我无法使用。 See image here.
    • 请注意,对于flavor1,我还创建了一个' res'目录,它确实变成了蓝色,但尽管如此,如果我想为不同的口味使用不同的resoruces,它不能提供创建Android资源文件或Andorid资源目录的能力。
  5. 我做错了吗?或者我错过了什么?如果您需要更多信息,请告诉我。

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

    **我检查了gradle设置,显然使用自动导入already enabled.尽管如此,还要对build.gradle文件doesn't automatically update进行更改。 注意:我也尝试过使用Build - Rebuild Project和/或Build - Make Project,禁止使用。我仍然需要关闭项目,并重新打开以使更改生效。

7 个答案:

答案 0 :(得分:216)

如果您已进入Studio首选项,请在Gradle部分下,为项目启用自动导入(我们稍后会默认启用此功能)。这样,只要您编辑它,Studio就会重新导入您的build.gradle。

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

如果你看一下my IO talk,你会看到我们如何将风味和构建类型中的值混合在一起来创建变体。

对于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 /...中的类所使用的API时。

编辑以匹配修订后的问题

此外,将相同的A类仅放在互斥的源文件夹中非常重要。在这种情况下,src / flavor1 / java和src / flavor2 / java永远不会被一起选中,但是main和flavor1是。

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

请注意,如果您有3种口味并且只想要一个自定义的flavor1,而flavor2和flavor3共享相同的活动,您可以为这两个其他活动创建一个共同的源文件夹。您可以灵活地创建新的源文件夹并配置源集以使用它们。

关于你的其他观点:

第二个风味源文件夹不是蓝色是正常的。您需要切换到第二种风格才能启用它,然后您就可以在其中创建包和类。在此之前,Studio并不认为它是源文件夹。我们希望将来能够改进这一点,以使IDE了解那些 unactive 源文件夹。

我认为您无法在res文件夹中创建资源文件也很正常。菜单系统尚未更新以处理所有这些额外资源文件夹。这将在稍后出现。

答案 1 :(得分:18)

"产品口味"在Android上

我有时会被问及如何使用不同的主机,图标甚至包名,在同一个应用的不同版本上进行处理。

有很多理由可以做到这一点,还有一个简单的方法:产品口味。

您可以在build.gradle脚本中定义我之前描述的这些事情。

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

产品风格定义项目构建的应用程序的自定义版本。单个项目可以有不同的风格,可以更改生成的应用程序。

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

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

现在,我们的应用程序有两种不同的风格。您也可以在Build Variants选项卡

中的Android Studio上查看它

构建变体

多个包名称

如果您希望在手机上安装一个具有开发状态且一个用于生产状态的应用,该怎么办?您可能知道,您只能安装一个具有相同程序包名称的应用程序(如果您尝试安装一些与手机上安装的相同的新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,请选择构建&gt;从主菜单生成签名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-flavours-on-android/

答案 2 :(得分:7)

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

关于其他源目录,您似乎需要手动创建它们:src/flavor1/javasrc/flavor2/java。您将看到在“Build Variants”视图中更改风格将更改当前活动的源目录(当目录为活动源目录时,目录为蓝色)

最后,“gradle将为您的新口味创建新的sourceSet”意味着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)

答案 3 :(得分:2)

当我将项目迁移到Gradle时,我遇到了同样的问题。 问题是构建没有找到合适的资源文件夹。 我通过在build.gradle中的android元素下添加它来修复它:

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

答案 4 :(得分:0)

重要且阻止了我一段时间的东西是需要匹配包的flavor名称,而不是gradle中flavor定义中定义的包。例如:

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

将匹配

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

但是

src/foobar/java/com/foo/A.java不会用于flavor1版本。

答案 5 :(得分:0)

Gradle:

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

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

然后为你添加你需要的口味

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}

答案 6 :(得分:0)

在gradle中配置风味之后,为了使react-native可以查看项目文件夹根目录中的自定义.env文件,您必须将其添加到 android/app/build.gradle

在我的示例中,我使用相同的代码库为Android设备创建了两个应用,一个用于group1,一个用于group2

//将此添加到您的app/build.gradle的第3行

project.ext.envConfigFiles = [
projecta: ".env.development.android.projecta",
projectb: ".env.development.android.projectb",
]

//别忘了添加

android {
compileSdkVersion rootProject.ext.compileSdkVersion
flavorDimensions “default” // add this line
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8

}

然后将数组中的键与您的产品口味匹配

  productFlavors {
    project1 {
        minSdkVersion rootProject.ext.minSdkVersion
        applicationId 'com.nativeapp.project1'
        targetSdkVersion rootProject.ext.targetSdkVersion
        resValue "string", "build_config_package", "com.nativeapp"
    }
    project2 {
        minSdkVersion rootProject.ext.minSdkVersion
        applicationId 'com.nativeapp.staff'
        targetSdkVersion rootProject.ext.targetSdkVersion
        resValue "string", "build_config_package", "com.nativeapp"
    }
}

还要确保applicationId和resValue以您的应用程序包名称开头

在我的情况下,它是“ nativeapp”,但您可以在MainActivity.java文件中找到您的文件。

如果您进入android / app / main / java / com /目录,则可以找到此文件。

之后,您可以在需要时配置脚本,如下所示:

"scripts": {
"android:project1": "ENVFILE=.env.development.candidate react-native run-android --variant=projectaDebug --appIdSuffix=projecta",
"android:staff": "ENVFILE=.env.development.staff.android react-native run-android --variant=projectbDebug --appIdSuffix=projectb",}

注意:添加脚本时,变体必须是风味名称,例如'project2',后跟'Debug'='projectb',因为这是您的默认buildType

还要确保您已在android / app / src /中为每种口味创建了相关文件夹。

就我而言

android/app/src/projecta/
android/app/src/projecta/

如果所有设置均正确,则在使用创建的脚本进行构建时,应创建正确的res文件夹和android清单文件。

如果要更改每个单独的应用程序实例的名称,请更改res/values目录中的strings.xml。

<resources>
<string name="app_name">Project1</string> //this will be the name of your app when its built in your emulator
</resources>