使用构建风格-正确构建源文件夹和 Build.gradle

请注意: Xavier 答案后编辑的答案

我试图在 Android Studio 中为同一个应用程序项目使用不同的 建立口味。然而,我似乎有一个可怕的时间配置它适当的工作。

步骤:

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

    productFlavors {
    flavor1 {
    packageName 'com.android.studio.test.flavor1'
    }
    flavor2 {
    packageName 'com.android.studio.test.flavor2'
    }
    }
    
  3. After restarting Android Studio, I now see 4 build variants under the Build Variants section. Meaning we were succesful on seting up the product flavors so far. **
  4. Created a new Source folder for flavor1; however, I am not sure if I'm doing it the right way. Here's how I did it:

    • Keep in mind that my Package name for this project is: com.foo.test
    • Right click on the src folder, for flavor1, I actually created the individual folders in the explorer, in a way that the structure is src/flavor1/java/com/foo/test/MainActivity.java.
    • The above worked well, since the 'java' folder is in blue, meaning the IDE knows its an active source directory. Also, the package was automatically created. Despite of this, I am getting a warning for duplicate class found. See screenshot here.
    • For flavor2, I tried creating the package manually, but 'src' folder for flavor2 seems not be in blue, and therefore the options are different when right clicked, and 'New Package' is not available for me to use. See image here.
    • Note that for flavor1, I also created a 'res' directory, which does turn blue, but despite of that, doesn't offer the ability to create either an Android Resource file, or Andorid resource directory, in case I wanted to use different resoruces for different flavors.

Am I doing something wrong? Or am I missing something? Let me know if you need more info.

*My Project seems to have two build.gradle files. One located on the root of the project folder (\GradleTest), this one is empty. The second one located on the root of a subfolder of \GradleTest, also labeled 'GradleTest' (GradleTest-GradleTest), this is the one that already had code when opened; therefore, that is the one I edited.

** I checked gradle settings and apparently Use auto-import was already enabled. Despite of this, making changes to the build.gradle file doesn't automatically update the build variants. Note: I also tried using Build - Rebuild Project, and/or Build - Make Project, no-go. I still have to close the project, and re-open for changes to take effect.

96074 次浏览

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

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

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

如果您进入了 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 和 Flavor1是一起选择的。

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

请注意,如果你有3种口味,只想要一个自定义的风味1,而风味2和风味3共享相同的活动,你可以为这两个其他活动创建一个共同的源文件夹。在创建新的源文件夹和配置源集以使用它们方面具有完全的灵活性。

关于你的其他观点:

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

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

我把项目迁移到 Gradle 时也遇到了同样的问题。 问题是构建没有找到合适的资源文件夹。 我在 build.gradle 中的 android 元素下面添加了这个:

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

一些重要的事情阻碍了我相当一段时间,是味道名称,需要匹配的包,而不是包内定义的味道定义在分级。例如:

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

会匹配

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

但是

src/foobar/java/com/foo/A.java将不会用于味道1的构建。

分级:

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

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

然后加入你需要的口味

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

Android 上的“产品风味”

有时我会被问到如何使用不同的主机、图标,甚至包名,这取决于同一个应用程序的不同版本。

有很多理由这样做,一个简单的方法去: 产品口味。

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

产品风味 这篇文章的一部分是关于产品风格的思考,那么,它们是什么呢? 关于 Android 文档:

产品风格定义了由项目构建的应用程序的自定义版本。单个项目可能有不同的风格,这些风格会改变生成的应用程序。

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

productFlavors {
...
devel {
...
}


prod {
...
}
}

现在,我们的应用程序将有两种不同的风格。你也可以在 AndroidStudio 的 BuildVariants 选项卡中检查它

构建变量

多个包名

如果您想在您的手机上安装一个应用程序的开发状态和一个生产状态。正如您可能知道的,您只能安装一个具有相同软件包名称的应用程序(如果您尝试安装与您的手机上安装的 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"'


}
}
}

作为一个示例,我们将尝试向您展示如何将这个功能集成到便于发送请求到适当的服务器,而不需要处理您所指向的服务器,并且基于风格。下面是 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,请从主菜单中选择 Build > Generate Signed 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/

在您的级别配置风味,以便允许反应原生看看定制。您必须添加到的项目文件夹根目录中的 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>