Android Studio Gradle指定特定于Flavor

时间:2017-08-17 00:40:16

标签: android android-studio gradle android-productflavors

我已经在Android Studio中实现了Flavors,现在我尝试将每个Flavor放在它自己的目录中,并使用自己独特的名称 - 遗憾的是,在某些情况下,名称与名称不同。 :(

我们的工具取决于它是否相同,所以如果我可以在gradle中将其拉出来,那就更好了。

我有一个使用版本名称后缀值作为目录名称并且有效的示例。但我想要做的是在flavor配置中的某个地方指定一个值,但是我发现当你设置一个具有相同名称的属性时,最后一个获胜 - 而不是按照配置中的指定使用每个属性。

所以,举个例子,假设我有两个口味:Jimbo和Randolph。但是我想把Jimbo.apk放在" jimmy"文件夹和Randolph.apk在" randy"夹。如何为每个将被选中并用于存储生成的APK的值(目录)指定?为了增加复杂性,我正在applicationVariants.all重命名APK当前。

在下面的代码中,我希望以某种方式用我能以某种方式指定的变量替换versionNameSuffix

这就是我所拥有的:

apply plugin: 'com.android.application'

    android {
        compileSdkVersion 25
        buildToolsVersion '25.0.2'
        defaultConfig {
            applicationId "com.mycompany.default"
            minSdkVersion 14
            targetSdkVersion 23
            versionCode 11
            versionName "1.0.11"
            compileOptions {
                sourceCompatibility JavaVersion.VERSION_1_7
                targetCompatibility JavaVersion.VERSION_1_7
            }
            signingConfig signingConfigs.config
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
        }
        productFlavors {
            Randolph {
                applicationId 'com.mycompany.randy'
                versionNameSuffix 'randy'
            }
            Jimbo {
                applicationId 'com.mycompany.jimmy'
                versionNameSuffix 'jimmy'
            }
        }


        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.productFlavors[0].versionNameSuffix + "/"
                logger.error("Path = " + path)
                def SEP = "-"
                def flavor = variant.productFlavors[0].name
                def version = variant.versionCode
                def newApkName = path + version + SEP + flavor
                logger.error("newApkName = " + newApkName)
                output.outputFile = new File(newApkName + ".apk")
            }
        }
    }

    dependencies {
        }

}

更新

根据使用任务的问题,我尝试了这种方法,但设置目录的问题仍然存在 - 使用属性(archivesBaseName)使用最后一个集,因此所有文件都被复制到该目录。这是一个例子。由于我有超过100种口味要创建,我希望每个都发送到它自己的目录和配置驱动。这是我试过的:

productFlavors {
    Randolph {
        applicationId 'com.mycompany.randy'
        setProperty("archivesBaseName", "randy")
    }
    Jimbo {
        applicationId 'com.mycompany.jimmy'
        setProperty("archivesBaseName", "jimmy")
    }
}


   applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def path = "C:/AndroidBuilds/MyCompany.Build/" + archivesBaseName + "/"
            logger.error("Path = " + path)
            def SEP = "-"
            def flavor = variant.productFlavors[0].name
            def version = variant.versionCode
            def newApkName = path + version + SEP + flavor
            logger.error("newApkName = " + newApkName)
            output.outputFile = new File(newApkName + ".apk")
            def copyApkTask = tasks.create(name: "copy" + variant.name + "Apk") {
                copy {
                    def newName = newApkName + ".apk"
                    logger.error("from = " + newName)
                    logger.error("into = " + path)
                    logger.error("old name = " + version + SEP + flavor + ".apk")
                    logger.error("new name = " + flavor + ".apk")
                    from newName
                    into path
                    rename (version + SEP + flavor + ".apk", flavor + ".apk")
                }
            }
            copyApkTask.mustRunAfter variant.assemble
        }
    } 

在上面的示例中,我添加了一项任务,以便将具有不同名称的APK另外复制到特定于风味的目录。所有的APK最终都被复制到最后指定的`archivesBaseName,即" jimmy"。所以最后一个赢了。我希望它会像一个变量。我宁愿不要有100多个if语句来执行此操作,并且更愿意在Gradle中执行此操作。我开始怀疑是否需要进行外部Ant调用以使这一切都能正常工作。

2 个答案:

答案 0 :(得分:1)

问题是setProperty正在设置Project属性,因此它总是被覆盖。一个简单的解决方案是使用Varients Extra Property。这样的事情。

productFlavors {
     Randolph { 
         applicationId 'com.mycompany.randy'
        ext.archivesBaseName = "randy" }
    Jimbo { 
        applicationId 'com.mycompany.jimmy'
        ext.archivesBaseName=jimmy" } 
    }

然后您将在任务中访问它

def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.ext.archivesBaseName + "/" 

我还没有测试过它,它可能有一个错误,需要一些调整。

<强>更新
这还不够,因为Gradle将设置为flavor对象的ext属性,只有在flavor对象中定义它。否则,它将在父对象或根对象中设置它,即项目。因此,为了使其工作,我们首先必须在flavor对象中定义属性。这可以在@Stephen在下面回答时完成。按照他的测试方法。

还有3个选项:
1.通过预先挂起样式名称,为每个样式使用不同的变量名称,例如&#34; Jimbo_archivesBaseName&#34;。然后使用property(flavorName +&#34; _archivesBaseName)访问它;
2.使用全局HashMap变量,为每个flavor名称设置路径 3.使用一个函数,它返回一个基于flavor名称的路径。

答案 1 :(得分:1)

好的,最后这个特定的链接真的帮助了我需要的变量赋值:

Android Studio: Gradle Product Flavors: Define custom properties

基本上你可以在风味中分配变量。这是我最终做的事情,实际上比我开始时更进一步,因为现在我可以使用Flavor作为APK名称或指定一个(我知道,它搞砸了,但历史可以这样!) :

apply plugin: 'com.android.application'

    android {
        compileSdkVersion 25
        buildToolsVersion '25.0.2'
        defaultConfig {
            applicationId "com.mycompany.default"
            minSdkVersion 14
            targetSdkVersion 23
            versionCode 11
            versionName "1.0.11"
            compileOptions {
                sourceCompatibility JavaVersion.VERSION_1_7
                targetCompatibility JavaVersion.VERSION_1_7
            }
            signingConfig signingConfigs.config
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
        }

        productFlavors.whenObjectAdded { flavor ->
            // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue'
            flavor.ext.set('directoryPath', '')
            flavor.ext.set('apkName', '')
        }

        productFlavors {
            Randolph {
                applicationId 'com.mycompany.randy'
                directoryPath =  'randy'
                apkName = 'RandyBoy'  // If you want the APK name be different than the flavor
            }
            Jimbo {
                applicationId 'com.mycompany.jimmy'
                directoryPath =  'jimmy'
            }
        }

        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.productFlavors[0].directoryPath + "/"
                def SEP = "-"
                def apkName = variant.productFlavors[0].apkName
                def flavor = variant.productFlavors[0].name
                if (apkName != '')
                    flavor = apkName;
                def version = variant.versionCode
                def newApkName = path + version + SEP + flavor
                logger.error("newApkName = " + newApkName)
                output.outputFile = new File(newApkName + ".apk")
            }
        }
    }

    dependencies {
        }

}

因此productFlavors.whenObjectAdded设置每种风味的默认值,然后由每种风味覆盖。在applicationVariants.all中,检查是否已覆盖apkName,如果是,则使用它,否则它使用flavor名称(并且版本代码在其前面添加)。该目录由味道直接设置。

非常感谢@lionscribe。他让我更清楚地思考这个问题。