Gradle 在 Android 上使用不同的密钥签署口味

Gradle signing flavors with different keys on Android

我的 Android 应用有多种风格,我希望除一个以外的所有应用都使用相同的密钥。有一个需要使用不同的密钥。

如何仅针对应用程序的一种风格覆盖 signingConfig(但在相同的构建类型中,例如 "release")?

最后一点很重要,因为我目前有超过 120 种不同的口味并且还在不断增加。为了单独定制每一种口味是很多额外的工作。


相关post我试过:

Producing multiple builds signed with different keys from single build type

Signing product flavors with gradle

Debug Signing Config on Gradle Product Flavors

总的来说,每个解决方案似乎仍然使用默认的发布配置,而不是我的自定义配置。


我的 build.gradle 的重要部分如下所示:

signingConfigs {
    releaseConfig {
        storeFile file('key')
        storePassword "pass"
        keyAlias "alias"
        keyPassword "pass"
    }

    custom {
        storeFile file('custom_key')
        storePassword "pass"
        keyAlias "alias"
        keyPassword "pass"
    }
}

productFlavors {
    apple {
        applicationId "demo.apple"
    }
    banana {
        applicationId "demo.banana"
    }

    // def customConfig = signingConfigs.custom
    custom {
        applicationId "custom.signed.app"
        // signingConfig customConfig
    }
 }


buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
    release {
         signingConfig signingConfigs.releaseConfig
         // productFlavors.custom.signingConfig signingConfigs.custom
    }
}

您必须在 buildTypes 中定义签名配置。将自定义签名配置添加到调试构建类型或创建自定义构建类型

    buildTypes {
        debug {
            applicationIdSuffix ".debug"
             signingConfig signingConfigs.custom
        }
        custom {
            applicationIdSuffix ".custom"
             signingConfig signingConfigs.custom
        }
        release {
             signingConfig signingConfigs.releaseConfig
        }
}

Gradle 将为每种构建类型创建风格,并且根据构建类型,风格将使用相应的登录配置。通过以上构建类型的配置,让我们考虑 "apple" 风格。 Gradle 将为苹果创建以下构建变体

  • appledebug --> 自定义签名配置
  • applecustom --> 自定义签名配置
  • applerelease --> 发布签名配置

    您可以 select 相应的构建变体和 运行 您的应用程序

将签名配置添加到 flavor

productFlavors {
    def customSigningConfig = signingConfigs.custom

    custom {
        ...
        signingConfig customSigningConfig
        ...
    }

您需要先声明您的签名配置,然后再声明您的口味。

https://code.google.com/p/android/issues/detail?id=64701

我不是 100% 确定这会起作用,但我认为您不想创建新的构建类型。这将为每种口味创建一个新的构建变体。当你真的只想要一种口味来覆盖 "default config" :)

此代码未经测试,但您应该能够按照以下方式执行某些操作:

signingConfigs {
    normal {
        storeFile file('key')
        storePassword "pass"
        keyAlias "alias"
        keyPassword "pass"
    }

    custom {
        storeFile file('custom_key')
        storePassword "pass"
        keyAlias "alias"
        keyPassword "pass"
    }
}

    /**
     *  defaultConfig is of type 'ProductFlavor'.
     *
     *  If we need to use a different signing key than the default,
     *  override it in the specific product flavor.
     */

    defaultConfig {
        versionCode 123
        versionName '1.2.3'
        minSdkVersion 15

        def standardSigningConfig = signingConfigs.normal

        buildTypes{
            release {
               signingConfig standardSigningConfig 
               zipAlign true
               // ...
            }
            debug { 
               //not sure you need this node
            }  
        }
    }


productFlavors {

    def customConfig = signingConfigs.custom
    def standardSigningConfig = signingConfigs.normal

    apple {
        applicationId "demo.apple"
    }
    banana {
        applicationId "demo.banana"
    }
    custom {
        applicationId "custom.signed.app"
        signingConfig customConfig
    }
}

参考:
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-Flavor-Configuration

一个想法可能是使用项目属性来确定您是否应该使用自定义登录配置。

if (project.hasProperty('custom')) {
    android.signingConfigs.release = customSigningConfig
} else {
    //should use the default
}

然后要构建您的自定义风味,您 运行:

gradle assembleCustomRelease -Pcustom=true

tl;dr 通过 "gradle.startParameter.taskNames" 寻找风味并修改变量。

我这样做是为了测试 Vine 应用程序的变体,结果非常好。您还可以使用它来编译不同的依赖项,而无需添加更多风味维度。

在你的情况下它看起来像这样。

            //root of buil.gradle OR probably inside buildTypes.release
            def signType = signingConfigs.normal;
            //You can put this inside builTypes.release or any task that executes becore
            def taskNames = gradle.startParameter.taskNames;
                taskNames.each { String name ->
                    if (name.contains("customFlavor")) {
                        signType = signingConfigs.custom
                    }
                }
            buildTypes{
                release {                   
                    signingConfig signType
                }
            }

Gradle Plugin User Guide 说你可以:

have each release package use their own SigningConfig by setting each android.productFlavors.*.signingConfig objects separately.

此答案中对此进行了演示 (Debug Signing Config on Gradle Product Flavors) and this blog post (Building Multiple Editions of an Android App with Gradle)。

但是,为每种口味指定一个单独的 signingConfig 行并不能很好地扩展,并且超出了问题的范围。不幸的是 none 所提供的答案显示了如何正确地覆盖 signingConfig


这个技巧来自这个答案 (How to get the currently chose build variant in gradle?),它展示了如何遍历构建变体(以及通过扩展,flavors)。

我的解决方案使用一个循环来为每种口味设置 signingConfig,而不是单独一行。这可以很好地扩展。 "override" 是用一行指定循环后的自定义配置完成的。

将以下代码放入 buildTypes.release 块中:

// loop over all flavors to set default signing config
productFlavors.all { flavor ->
    flavor.signingConfig signingConfigs.releaseConfig
}
// override default for single custom flavor
productFlavors.custom.signingConfig signingConfigs.custom

如果 signingConfig 没有在产品风格中指定,下面给出的代码将使用 release1 作为默认的 signingConfig。

app/build.gradle

signingConfigs {
    debug {
        storeFile file("/home/.../debugkeystore.jks")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }
    release1 {
        storeFile file("/home/.../testkeystore1.jks")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }
    release2 {
        storeFile file("/home/.../testkeystore2.jks")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }
    release3 {
        storeFile file("/home/.../testkeystore3.jks")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }
}

defaultConfig {
    applicationId "com.example.signingproductflavors"
    minSdkVersion 15
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    signingConfig signingConfigs.release1
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    debug { 
        signingConfig signingConfigs.debug
    }
}

productFlavors {
    blocks {
        applicationId "com.example.blocks"
        resValue 'string', 'APP_NAME', "Blocks"
    }
    cloud {
        applicationId "com.example.cloud"
        resValue 'string', 'APP_NAME', "Cloud"
        signingConfig signingConfigs.release2
    }
    deck {
        applicationId "com.example.deck"
        resValue 'string', 'APP_NAME', "Deck"
        signingConfig signingConfigs.release3
    }
}