Gradle-唯一的解决方法是根据Build Variant修改App名称

Gradle-only solution to modify App name based on Build Variant

我正在尝试修改我的 gradle 文件,以便根据 FlavorBuild Type 为我的应用程序使用不同的名称。到目前为止,我已经成功地通过 Android Gradle Plugin Docs

使用 Manifest Merging 技术使基于 Flavor 的命名变得简洁

当前

这些是我的 debugrelease 版本在主屏幕上的应用程序名称。

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name                   App Name
entity_2   App Name                   App Name
...        ...                        ...
entity_2   App Name                   App Name
hub        Hub                        Hub

它很接近,但是...

需要

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name - Entity_1_name   App Name
entity_2   App Name - Entity_2_name   App Name
...        ...                        ...
entity_n   App Name - Entity_n_name   App Name
hub        Hub                        Hub

我想要这个,这样我就可以知道主屏幕上的 debug 口味。我不关心区分 release 口味,因为用户在他们的设备上只会有一个(可能有多个,但我不关心)

考虑到 Gradle 的可扩展性,我认为这是可能的;但是,我不是高级 Gradle 用户。

那么,我怎样才能(尽可能)简洁地扩展我的代码以获得我想要的输出?

注意:以上表格使用versionNameSuffix作为我的应用名称的后缀;但是,它可以是任何东西(另一个添加的变量??),它可以让我知道我只在我的调试构建类型中使用哪种风格。

非目标

代码

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "..."
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [ applicationLabel:"App Name"]
    }

    productFlavors {
        entity_1 {
            versionNameSuffix ' - Entity_1_name'
            applicationIdSuffix 'entity_1'
        }
        entity_2 {
            versionNameSuffix ' - Entity_2_name'
            applicationIdSuffix 'entity_2'
        }
        hub {
            versionNameSuffix ' - Hub'
            applicationIdSuffix 'hub'
            manifestPlaceholders = [ applicationLabel:"Hub" ]
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

清单

<manifest ...>

    <application
        ...
        android:label="${applicationLabel}"
        ... >

更新

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    ext {
        APP_NAME = "App Name"
        HUB_NAME = "Hub"
    }

    defaultConfig {
        applicationId "..."
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    productFlavors {
        one_million {
            versionNameSuffix ' - Entity_1'
            applicationIdSuffix 'entity_1'
            manifestPlaceholders = [ applicationLabel: APP_NAME + versionNameSuffix ]
        }
        udacity {
            versionNameSuffix ' - Entity_2'
            applicationIdSuffix 'entity_2'
            manifestPlaceholders = [ applicationLabel: APP_NAME + versionNameSuffix ]
        }
        hub {
            versionNameSuffix ' - Hub'
            applicationIdSuffix 'hub'
            manifestPlaceholders = [ applicationLabel: HUB_NAME ]
        }
    }

    buildTypes {
        release {
            manifestPlaceholders = [ applicationLabel: APP_NAME ]
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

新输出

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name - Entity_1_name   App Name
entity_2   App Name - Entity_2_name   App Name
...        ...                        ...
entity_n   App Name - Entity_n_name   App Name
hub        Hub                        App Name          <- Issue (Release)

第一次尝试比更新后的代码更接近正确答案。

可以通过将所有 manifestPlaceholders 代码移动到 applicationVariants.all 部分来进一步重构;然而,这是一个半干净的、仅 gradle 解决方案的工作副本...

android {
    ext {
        APP_NAME = "App Name"
        HUB_NAME = "Hub"
    }
    defaultConfig {
        manifestPlaceholders = [ applicationLabel: APP_NAME ]
    }
    productFlavors {
        entity_1 {
            versionNameSuffix ' - Entity_1'
            applicationIdSuffix 'entity_1'
        }

        ...

        entity_n {
            versionNameSuffix ' - Entity_n'
            applicationIdSuffix 'entity_n'
        }

        hub {
            versionNameSuffix ' - Hub'
            applicationIdSuffix 'hub'
            manifestPlaceholders = [ applicationLabel: HUB_NAME ]
        }
    }

    applicationVariants.all { variant ->
        // Don't modify the release build or the hub flavor. They are good already.
        if (variant.buildType.name == "release" || variant.flavorName == "hub") return
        variant.mergedFlavor.manifestPlaceholders = [applicationLabel: APP_NAME + variant.mergedFlavor.versionNameSuffix]
    }

备注:

BEFORE applicationVariants.all { ... } 代码运行,这就是所有 applicationLabel 的样子。我们很接近,但需要添加到他们...

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name                   App Name
entity_2   App Name                   App Name
...        ...                        ...
entity_n   App Name                   App Name
hub        Hub                        Hub

AFTER applicationVariants.all { ... } 代码运行后,这就是所有 applicationLabel 的样子。我们完成了!

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name - Entity_1_name   App Name
entity_2   App Name - Entity_2_name   App Name
...        ...                        ...
entity_n   App Name - Entity_n_name   App Name
hub        Hub                        Hub

还有...

defaultConfig 无法访问个人 productFlavors 内的信息。尽管 defaultConfigFlavor 的一种,但只有指定的 Flavors 才能从 defaultConfig 中读取信息。没有机制可以走另一条路(据我所知)。所以你需要在defaultConfig

中设置最通用的类​​型

buildTypes 块中的任何信息都有最终决定权,applicationVariants.all 中的代码不会覆盖它。为了克服这个问题,您必须从 buildType 块中删除所需的代码并将其移动到 applicationVariants.all 块中(使用正确的逻辑语句)

Christopher 的解决方案对我不起作用。我又花了几个小时尝试不同的模式,终于找到了适合我的情况,所以我会在这里分享它。

首先,build.gradle中的productFlavors定义:

productFlavors {

    uat {
        manifestPlaceholders.appNameSuffix = " UAT"
    }

    live {
        manifestPlaceholders.appNameSuffix = ""
    }
}

然后,构建类型:

buildTypes {

    debug {
        manifestPlaceholders.appName = "Preg Debug"
    }

    qa {
        manifestPlaceholders.appName = "Preg QA"
    }

    release {
        manifestPlaceholders.appName = "Pregnancy"
    }

}

最后但同样重要的是,android:label 在清单 > 应用程序中:

    android:label="${appName}${appNameSuffix}"

因此,我得到了应用名称的以下 6 个变体:

  • 怀孕
  • 怀孕 UAT
  • 预检质量检查
  • Preg QA UAT
  • 预调试
  • 预调试 UAT

所以,结论是,我必须在清单文件中连接来自产品风格和构建类型的清单占位符,等等!

在干净、可读和可维护方面,我认为这是要走的路:)