使用渐变签署产品风味

我正在努力将我的项目转移到分级。我的一个项目有多种产品风格,每一种都必须在其发行版中使用不同的 signingConfig进行签名。这就是我到目前为止所做的尝试:

buildscript {
...
}


apply plugin: 'android'


android {
compileSdkVersion 17
buildToolsVersion '17'


signingConfigs {
flavor1 {
storeFile file("keystore")
storePassword "secret"
keyAlias "aliasForFlavor1"
keyPassword "secretFlavor1"
}


flavor2 {
storeFile file("keystore")
storePassword "secret"
keyAlias "aliasForFlavor2"
keyPassword "secretFlavor2"
}
}


productFlavors {
flavor1 {
signingConfig signingConfigs.flavor1
}


flavor1 {
signingConfig signingConfigs.flavor2
}
}
}


dependencies {
...
}

当我运行 gradle build时,我得到一个 groovy.lang.MissingFieldException和下面的错误消息:

No such field: signingConfigs for class: com.android.build.gradle.internal.dsl.GroupableProductFlavorFactory

因此,我假设 Gradle 脚本的 productFlavors.* 部分不是放置代码签名配置的正确位置。

34942 次浏览

Android 的 gradle 插件只支持每种构建类型的签名,而不支持每种风格的签名。这样做的原因是,任何给定的 变异(构建类型 + 风味)只能由一个键签名,但可以是几个风味组的组合。例如,您的风味组可以是 cpu (x86/arm)和版本(免费/付费) ,这里有四种不同的变体。

您正在寻找的解决方案是为不同的版本创建单独的构建类型。例如,您的构建类型可能是 debugreleaserelease-beta,如下所示:

...


android {


...


buildTypes {
debug {
signingConfig signingConfigs.debug
}


release {
signingConfig signingConfigs.release
}


release-beta {
initWith release
signingConfig signingConfigs.release-beta
}
}
}

上面的 initWith只是告诉 gradle release-beta应该是 release构建类型的一个副本,只是用不同的键签名。

根据 用户指南,支持为风味签名配置。

这里的问题与 signingConfig 对象的作用域有关。我只是将它分配给 productFlavors块内的一个变量,但是在 flavor1风格块外面修复了这个问题:

productFlavors {
def flavor1SigningVariable = signingConfigs.flavor1


flavor1 {
...
signingConfig flavor1SigningVariable
...
}

可以在 buildType中为每个 flavor声明 signing config。这是我的用不同密钥存储库进行发布签名的渐变文件。

android {
signingConfigs {
configFirst {
keyAlias 'alias'
keyPassword 'password'
storeFile file('first.keystore')
storePassword 'password'
}


configSecond {
keyAlias 'alias'
keyPassword 'password'
storeFile file('second.keystore')
storePassword 'password'
}
}


compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
}


productFlavors{
flavor1 {
applicationId "com.test.firstapp"
}


flavor2 {
applicationId "com.test.secondapp"
}
}


buildTypes {
release {
productFlavors.flavor1.signingConfig signingConfigs.configFirst
productFlavors.flavor2.signingConfig signingConfigs.configSecond


minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'


}
}
}

buildTypes块应该放在 productFlavors块之后,我的意思是顺序很重要。

也许是另一个有趣的解决方案,具有动态风味签名配置和其他优势

  • 我可以在 gradle 中定义应用程序 ID 和应用程序风味名称(这很清楚,每种风味只有两行) ,但我不想定义单独的签名配置(在添加风味时,gradle 文件会太长)
  • 我也不想有敏感的签名信息放在梯级,因为它承诺
  • 额外的好处是,调试版本有另一个应用程序 ID 和应用程序名称。

。吉蒂诺尔

...
/keystore.properties

Keystore.properties

storeFile=../mystore.jks
storePassword=...


keyAliasFlavor1=...
keyPasswordFlavor1=...


keyAliasFlavor2=...
keyPasswordFlavor2=...


App/build.gradle

def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(rootProject.file('keystore.properties')))


android {
...


buildTypes {
debug {
...
manifestPlaceholders = [appNameSuffix: " Dev"]
applicationIdSuffix ".dev"
}
release {
...
manifestPlaceholders = [appNameSuffix: ""]
productFlavors.all { flavor ->
flavor.signingConfig = android.signingConfigs.create("${flavor.name}")
flavor.signingConfig.storeFile = rootProject.file(keystoreProperties["storeFile"])
flavor.signingConfig.storePassword = keystoreProperties["storePassword"]
flavor.signingConfig.keyAlias = keystoreProperties["keyAlias${flavor.name}"]
flavor.signingConfig.keyPassword = keystoreProperties["keyPassword${flavor.name}"]
}
}
}


productFlavors {
Flavor1 {
applicationId "..."
manifestPlaceholders = [appNameBase: "MyApp 1"]
}
Flavor2 {
applicationId "..."
manifestPlaceholders = [appNameBase: "MyApp 2"]
}
// ... and many other flavors without taking care about signing configs
// (just add two lines into keystore.properties for each new flavor)
}
}

App/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application android:label="${appNameBase}${appNameSuffix}" ...>
...
</application>
</manifest>

GmsHms构建之间拆分签名配置

如果有人必须在 GmsHms构建版本之间分割他们的签名配置,这只是为了以后的参考。

这增加了这里列出的答案:
也许是另一个有趣的解决方案,具有动态风味签名配置和其他优势


建造,分级

选择一

gradle.startParameter.getTaskNames().each()

   def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))


signingConfigs {
release {
storeFile file(keystoreProperties["RELEASE_STORE_FILE"])
storePassword keystoreProperties["RELEASE_STORE_PASSWORD"]
keyAlias keystoreProperties["RELEASE_KEY_ALIAS"]
keyPassword keystoreProperties["RELEASE_KEY_PASSWORD"]
}
releaseHms {
storeFile file(keystoreProperties["RELEASE_HMS_STORE_FILE"])
storePassword keystoreProperties["RELEASE_STORE_PASSWORD"]
keyAlias keystoreProperties["RELEASE_KEY_ALIAS"]
keyPassword keystoreProperties["RELEASE_KEY_PASSWORD"]
}
debug {
// use default debug key to sign
}
}
    

buildTypes {
release {
...


gradle.startParameter.getTaskNames().each { task ->
if (task.toLowerCase().contains("gms")) {
signingConfig signingConfigs.release
}
if (task.toLowerCase().contains("hms") {
signingConfig signingConfigs.releaseHms
}
}
}


debug {
...


gradle.startParameter.getTaskNames().each { task ->
if (task.toLowerCase().contains("gms")) {
signingConfig signingConfigs.debug
}
if (task.toLowerCase().contains("hms") {
signingConfig signingConfigs.releaseHms
}
}


flavorDimensions "serviceplatform"
productFlavors {
hms {
dimension "serviceplatform"
applicationIdSuffix ".huawei"
versionNameSuffix "-huawei"
}
gms {
dimension "serviceplatform"
applicationIdSuffix ".android"
}
}


sourceSets {
main {
res.srcDirs = [
"src/main/res",
"src/main/res/layout/toolbar",
"src/main/res/layout/fragment",
"src/main/res/layout/activity"
]
}


gms {
java.srcDir("src/gms/java")
}
hms {
java.srcDir("src/hms/java")
}
}


选择二

productFlavors.gms.signingConfig

确保 flavorDimensionsbuildTypes之前

flavorDimensions "serviceplatform"
productFlavors {
hms {
...
}
gms {
...
}
}


buildTypes {
release {
...
productFlavors.gms.signingConfig signingConfigs.release
productFlavors.hms.signingConfig signingConfigs.releaseHms
}


debug {
...
productFlavors.gms.signingConfig signingConfigs.debug
productFlavors.hms.signingConfig signingConfigs.releaseHms
}
}


这是相当于 阿沙基洛夫的回答Kotlin DSL:

// See https://stackoverflow.com/q/60474010
fun getLocalProperty(key: String) = gradleLocalProperties(rootDir).getProperty(key)
fun String?.toFile() = file(this!!)
// Could also use System.getenv("VARIABLE_NAME") to get each variable individually
val environment: Map<String, String> = System.getenv()


android {
signingConfigs {
create("MyFirstConfig") {
keyAlias = getLocalProperty("signing.keyAlias") ?: environment["SIGNING_KEY_ALIAS"]
storeFile = (getLocalProperty("signing.storeFile") ?: environment["SIGNING_STORE_FILE"]).toFile()
keyPassword = getLocalProperty("signing.keyPassword") ?: environment["SIGNING_KEY_PASSWORD"]
storePassword = getLocalProperty("signing.storePassword") ?: environment["SIGNING_STORE_PASSWORD"]
enableV1Signing = true
enableV2Signing = true
}
create("MySecondConfig") {
keyAlias = getLocalProperty("signing.keyAlias2") ?: environment["SIGNING_KEY_ALIAS2"]
storeFile = (getLocalProperty("signing.storeFile2") ?: environment["SIGNING_STORE_FILE2"]).toFile()
keyPassword = getLocalProperty("signing.keyPassword2") ?: environment["SIGNING_KEY_PASSWORD2"]
storePassword = getLocalProperty("signing.storePassword2") ?: environment["SIGNING_STORE_PASSWORD2"]
enableV1Signing = true
enableV2Signing = true
}
}


productFlavors {
create("flavor1") {
// ...
}
create("flavor2") {
// ...
}
}


buildTypes {
getByName("release") { // OR simply  release {  in newer versions of Android Gradle Plugin (AGP)
productFlavors["flavor1"].signingConfig = signingConfigs["MyFirstConfig"]
productFlavors["flavor2"].signingConfig = signingConfigs["MySecondConfig"]
// OR alternative notation
// productFlavors {
//     getByName("flavor1") {
//         signingConfig = signingConfigs["MyFirstConfig"]
//     }
//     getByName("flavor2") {
//         signingConfig = signingConfigs["MySecondConfig"]
//     }
// }
}
}
}