Android Gradle中每个Flavor的代码路径

14

我有2个构建类型(debug、release)和2个产品风味(product1、product2)。我想为每个构建类型和产品风味定义一个buildConfigField。该buildConfigField是应用从服务器下载数据的URL,对于每个产品风味和构建类型都会发生变化。

现在,我的情况如下:

buildTypes {
    debug {
        debuggable true
    }
    release {
        debuggable false
    }
}
productFlavors {
    product1 {
        buildConfigField STRING, "URL_BASE",  '"https://api1.release.com"'

    }
    product2 {
        buildConfigField STRING, "URL_BASE", '"https://api2.release.com"'

    }
}

但我想要类似这样的东西:

buildTypes {
    debug {
        debuggable true
    }
    release {
        debuggable false
    }
}
productFlavors {
    product1 {
        debug {
            buildConfigField STRING, "URL_BASE",  '"https://api1.debug.com"'
        }
        release {
            buildConfigField STRING, "URL_BASE",  '"https://api1.release.com"'
    }
    product2 {
        debug {
            buildConfigField STRING, "URL_BASE", '"https://api2.debug.com"'
            }
        release {
            buildConfigField STRING, "URL_BASE", '"https://api2.release.com"'
        }
    }
}

我该如何实现这个目标?

更新:

每个URL_BASE都有不同的模式,所以我不能将它们分组。一种可能的解决方案是在不同的构建类型中添加2个版本的url base,并在flavor中选择正确的版本。

buildTypes {
    debug {
        debuggable true
        buildConfigField STRING, API_VARIANT_PRODUCT1, '"api1.deb.com"'
        buildConfigField STRING, API_VARIANT_PRODUCT2, '"api2.debug.com"'

    }
    release {
        debuggable false
        buildConfigField STRING, API_VARIANT_PRODUCT1, '"api1.release.com"'
        buildConfigField STRING, API_VARIANT_PRODUCT2, '"api2.release.com"'
    }
}

productFlavors {
    product1 {
        buildConfigField STRING, URL_BASE, '"https://" + API_VARIANT_PRODUCT1 + "/v1"'
    }
    product2 {
        buildConfigField STRING, URL_BASE, '"https://" + API_VARIANT_PRODUCT2 + "/v1"'
    }
  }
}

更新2

如果您需要在Gradle中添加资源,例如“KEY_MAP”,解决方案在此页面中。

4个回答

13

构建类型不是产品风味的一部分,反之亦然。Variant 是基于构建类型和产品风味两者计算的。使用这个,您可以创建一个扩展(选项 1)或属性(选项 2),并使用产品风味和构建类型的一致格式。

选项 1

ext.product1_release_base_url = 'http://baseurl.myproduct/public'
ext.product2_release_base_url = 'http://baseurl.yourproduct/secure'
ext.product1_debug_base_url = 'http://debugurl.myproduct/test'
ext.product2_debug_base_url = 'http://yourproduct/debug'

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false
        }
    }
    productFlavors {
        product1 {}
        product2 {}
    }
}

project.android.applicationVariants.all {variant ->
    def url = project.ext."${variant.flavorName}_${variant.buildType.name}_base_url"
    variant.buildConfigField('String', 'URL_BASE', "\"${url}\"")
}

选项2

在 gradle.properties 文件中

product1_release_base_url = 'http://baseurl.myproduct/public'
product2_release_base_url = 'http://baseurl.yourproduct/secure'
product1_debug_base_url = 'http://debugurl.myproduct/test'
product2_debug_base_url = 'http://yourproduct/debug'

在 build.gradle 文件中

android {
    buildTypes {
        release {}
        debug {}
    }
    productFlavors {
        product1 {}
        product2 {}
    }
}

project.android.applicationVariants.all {variant ->
    def url = project."${variant.flavorName}_${variant.buildType.name}_base_url"
    variant.buildConfigField('String', 'URL_BASE', "\"${url}\"")
}

我们需要显式调用 "project.android.applicationVariants.all" 吗? - Tushar Pandey
可能还有其他方法,但我不知道。没有声明式的方法可以做到这一点,这就是你所感兴趣的。 - n4h0y
请问为什么要使用 ""${url}"" 而不是直接使用 ${url}? - TapanHP
如何避免不存在的额外属性?例如,您意外添加了新的口味产品3,如何忽略它并继续循环? - david
@n4h0y,是的,我已经通过添加if project.hasProperty来避免不存在的额外属性了,谢谢。 - david
显示剩余2条评论

6

@Beni,你可以使用类似这样的东西


buildTypes {
    debug {
        debuggable true
        buildConfigField("String", "API_VARIANT", '"debugvariant"')
    }
    release {
        debuggable false
        buildConfigField("String", "API_VARIANT", '"releasevariant"')
    }
}
productFlavors {
    product1 {
        buildConfigField("String", "URL_BASE", '"https://api1." + API_VARIANT + ".com"')
    }
    product2 {
        buildConfigField("String", "URL_BASE", '"https://api2." + API_VARIANT + ".com"')
    }
}

你提出的方案存在问题,即每个buildType的最后一个定义 buildConfigField STRING, "URL_BASE"值将在所有产品风味中使用。 所以你最终会得到两个release版本中相同的东西,例如"https://api2.release.com"
使用上述方法,每个变体的BuildConfig文件将类似于以下内容。
// Fields from build type: debug
public static final String API_VARIANT = ["debugvariant"|"releasevariant"];
// Fields from product flavor: [product1|product2]
public static final String URL_BASE = "https://[api1|api2]." + API_VARIANT + ".com";

希望这能有所帮助。

我根据我的更新后的问题修改了代码。由于我有不同的URL方案,所以我不能以相同的方式应用你的答案,我必须进行适应,正如你所看到的那样。 - beni

1
applicationVariants.all { variant ->

   def apiVariant = variant.getFlavorName == "product1" ? "api1" : "api2"
   def server = variant.buildType.name == "debug" ? "debug" : "release"

   variant.buildConfigField STRING, URL_BASE, "http://" + apiVariant + "." + server + ".com"
}

1
我不知道如何使用buildConfigField方法为多个BuildVariants(构建类型+Flavor)设置不同的值,但是您可以在res/values/strings.xml中使用不同的值作为url_base。例如:
<string name="url_base">https://api1.debug.com</string>

然后您可以在这些文件夹中创建相同的字符串资源:

 - app/src/product1Debug: Contains product1-debug-related code/resources
 - app/src/product1Release: Contains product1-release-related code/resources
 - app/src/product2Debug: Contains product2-debug-related code/resources
 - app/src/product2Release: Contains product2-release-related code/resources

当然,在BuildConfig中有一个值并不同于使用build.gradle进行配置,而且不太舒适。

关于每个构建类型都相同的Java类,我该怎么办?我需要克隆每个Java类并将其添加到product1Debug、product1Release中吗?还是我需要创建一个名为product1的文件夹,并将此代码放在其中?例如,一个名为SplashActivity.java的Java类,在product1的debug和release构建类型中是相同的。谢谢。 - beni
对于Java类,您必须为每个buildTypes放置1个类。在这种情况下,您可以使用: - app/src/debug: - app/src/product1Release - app/src/product2Release - Gabriele Mariotti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接