简体   繁体   English

Android Studio Gradle指定特定于Flavor的输出目录

[英]Android Studio Gradle specifying output directory specific to Flavor

I have implemented Flavors in Android Studio and am now trying to place each Flavor in it's own directory, with its own unique name - sadly with a name different, in some cases, than the flavor name. 我已经在Android Studio中实现了Flavors,现在正尝试将每个Flavor放置在其自己的目录中,并使用其自己的唯一名称-遗憾的是,在某些情况下,其名称不同于Flavor的名称。 :( :(

We have tools depending on it being the same, so if I can pull that off in gradle, all the better. 我们拥有的工具取决于它是否相同,因此,如果我可以将其成功应用,那就更好了。

I have a sample that is using the version name suffix value as the directory name and that works. 我有一个使用版本名称后缀值作为目录名称的示例,并且可以正常工作。 But what I would like to do is specify a value somewhere in the flavor config that would be used, however I find that when you set a property with the same name the last one wins - rather than each being used as specified in the config. 但是我想做的是在flavor配置中的某个地方指定一个将要使用的值,但是我发现当您设置一个具有相同名称的属性时,最后一个将获胜-而不是按照配置中指定的方式使用每个属性。

So, for example, lets say I have two Flavors : Jimbo and Randolph. 例如,假设我有两种口味:Jimbo和Randolph。 However I want to place the Jimbo.apk in the "jimmy" folder and the Randolph.apk in the "randy" folder. 但是,我想将Jimbo.apk放在“ jimmy”文件夹中,将Randolph.apk放在“ randy”文件夹中。 How can I specify a value (directory) for each that will be picked up and used to store the generated APK? 如何为每个将指定的值(目录)指定并将其用于存储生成的APK? To add to the complexity I am renaming the APK current in the applicationVariants.all . 为了增加复杂性,我在applicationVariants.all重命名了当前的APK。

In the code below I am looking to somehow replace the versionNameSuffix with a variable I can somehow specify. 在下面的代码中,我正在寻找以某种方式可以将versionNameSuffix替换为我可以指定的变量。

Here is what I have: 这是我所拥有的:

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 {
        }

}

UPDATE UPDATE

Per the question of using a task, I tried this approach but the problem of setting the directory remains - using a property ( archivesBaseName ) the last one set is used so all the files are copied to that directory. 对于使用任务的问题,我尝试了这种方法,但是设置目录的问题仍然存在-使用属性( archivesBaseName ),使用了最后一组,因此将所有文件都复制到该目录。 Here is a sample of that. 这是一个示例。 Since I have upwards of 100 flavors to create I want each sent to it's own directory and config driven. 由于我要创建多达100种口味,因此我希望将每种口味发送到它自己的目录并进行配置驱动。 Here is what I tried: 这是我尝试过的:

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
        }
    } 

In the example above I added a task to additionally copy the APK with different name to a flavor specific directory. 在上面的示例中,我添加了一个任务,用于将具有不同名称的APK另外复制到特定风味的目录。 All the APKs end up copied to the last specified `archivesBaseName, which is "jimmy". 所有APK最终都复制到最后指定的“ archivesBaseName”,即“ jimmy”。 So last one wins. 所以最后一个赢了。 I was hoping it would act like a variable. 我希望它的作用像一个变量。 I would prefer not to have to have 100+ if statements to do this and would prefer to do this in Gradle. 我宁愿不必100个以上的if语句来执行此操作,也不希望在Gradle中执行此操作。 I am starting to wonder if I will need to make an external Ant call to make this all work. 我开始怀疑是否需要进行外部Ant调用才能使所有这些工作正常进行。

Ok, in the end this specific link REALLY helped on the variable assignment which is what I needed: 好的,最后,这个特定的链接确实对我需要的变量赋值有所帮助:

Android Studio: Gradle Product Flavors: Define custom properties Android Studio:Gradle产品风味:定义自定义属性

Basically you can assign variables within the flavor. 基本上,您可以在风味中分配变量。 Here is what I ended up doing, which actually went a bit further than when I started, since now I can use the Flavor as the APK name or specify one (I know, it is messed up, but history can be that way!): 这是我最终做的事情,实际上比开始时做的更多,因为现在我可以将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 {
        }

}

So productFlavors.whenObjectAdded sets the default values for each flavor, which are then overridden by each flavor. 因此, productFlavors.whenObjectAdded设置每种口味的默认值,然后默认值将被每种口味覆盖。 In the applicationVariants.all a check is made to see if the apkName has been overridden, if so it uses it, otherwise it uses the flavor name (and the version code is tacked in front of it). applicationVariants.all将进行检查以查看apkName是否已被覆盖,如果使用,则使用它,否则使用风味名称(版本代码附加在其前面)。 The directory is set directly by the flavor. 该目录由风味直接设置。

Big thanks to @lionscribe. 非常感谢@lionscribe。 He got me thinking this thru more clearly. 他让我更加清楚地思考了这一点。

The problem is that setProperty is setting the Project property, so it is always being overwritten. 问题在于setProperty正在设置Project属性,因此它总是被覆盖。 A simple solution is to rather use the Varients Extra Property. 一个简单的解决方案是使用Varients Extra属性。 Something like this. 这样的事情。

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

Then you will access it in the task as 然后您将在任务中访问它

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

I haven't tested it, and it may have a bug, and need some tweaking. 我尚未对其进行测试,它可能存在错误,需要进行一些调整。

Update 更新
This is not enough, as Gradle will set to the ext property of the flavor object, only if it is defined in the flavor object. 这还不够,因为仅当在Gradle对象中定义Gradle时,Gradle才会将其设置为Flavor对象的ext属性。 Otherwise it will set it in the parent or root object, which is the project. 否则,它将在项目的父对象或根对象中进行设置。 So for this to work, we first have to define the property in the flavor object. 因此,要使其正常工作,我们首先必须在味道对象中定义属性。 This can be done as @Stephen has answered below. 这可以通过@Stephen在下面回答来完成。 Follow his tested method. 遵循他的测试方法。

There are 3 more options: 还有3个选项:
1. Use a different variable name for each flavir, by pre-pending the flavor name, like "Jimbo_archivesBaseName". 1.通过在风味名称前加上“ Jimbo_archivesBaseName”,为每个黄病毒使用不同的变量名称。 Then access it using property(flavorName + "_archivesBaseName); 然后使用property(flavorName +“ _archivesBaseName);访问它;
2. Use a global HashMap variable, setting a path for each flavor name. 2.使用全局HashMap变量,为每个风味名称设置路径。
3. Using a function, that returns a path based on flavor name. 3.使用一个函数,该函数根据风味名称返回路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM