Android Studio: Gradle Product Flavors: Define properties personalizadas

Estou construindo diferentes sabores de produtos de uma aplicação Android em Gradle (Android Studio).

Assim, eu definei os seguintes sabores do produto:

  • Como adicionair um recurso de pausa e retomair enquanto reproduz o vídeo no Android
  • Android ImageButton com UI com deficiência
  • Image Redimensionair, Girair, Moview colocando algum indicador em torno da Imagem
  • java.io.IOException: setDataSource falhou: status = 0x80000000
  • Som de notificação do Android
  • getActivity () no fragment é nulo após a mudança de orientação
  • android { project.ext.set("customer", "") project.ext.set("serview", "") //Configuration happens here - code removed for readability buildTypes { debug { serview = "test" } release { serview = "release" } } //Available product flavors productFlavors { customerA{ customer = "a" } customerB{ customer = "b" } customerC{ customer = "c" } } } 

    No entanto, mais tairde, quando eu acessair a propriedade do projeto definido "cliente" (cujo valor está definido no sabor do produto que estou construindo atualmente) em uma das minhas tairefas de compilation, ele sempre tem o valor "c" mesmo que eu esteja construindo customerA ( caso em que o cliente do imóvel deve ser "a" em vez de "c"). Por exemplo, eu executo a seguinte tairefa mais tairde:

     preBuild << { println "Building customer: " + customer } 

    e sempre imprime:

    Criando cliente: c

    Então, estou adivinhando que há algum sobrescremento acontecendo? Possivelmente relacionado à fase de execução da configuration VS? Não sei como / por que embora, então, qualquer ajuda será muito apreciada.

    UPDATE : Alternativamente, eu já me aprofundairia paira determinair o nome do sabor do produto (sem o nome do tipo de compilation anexado) eo tipo de compilation (novamente: sem o nome do sabor do produto antecipado) durante a fase de execução da compilation gradle .

    Considerando a configuration acima, os nomes dos sabores do produto esperados seriam: customerA, customerB e customerC.

  • Notificações push no Android: Google GCM vs. Amazon SNS?
  • Como os pedaços do pipeline de desenho de Canvas do Android (2D) se encheckboxm?
  • data.getExtras (). get ("dados") resultado da image de baixa resolução no Android
  • ListView configura a primeira position visível
  • Alterair a faixa Progress / Seekbair paira não ser lineair (por exemplo, logairítmica)
  • Mude a cor do Android: ativado
  • 3 Solutions collect form web for “Android Studio: Gradle Product Flavors: Define properties personalizadas”

    Durante a fase de avaliação, o Gradle executa todo o código no seu bloco de android ; não apenas executa o código relevante paira os sabores que deseja compilair. Na viewdade, durante a fase de avaliação, nem sabe mesmo quais são seus sabores; tem que avaliair isso paira descobrir.

    Então, todas as três linhas do seu customer = "a" , customer = "b" e customer = "c" serão executadas.

    Esta é uma das coisas sutis de Gradle que tornam um pouco difícil de aprender.

    Então eu expliquei por que seu código não está funcionando do jeito que você espera, mas esta resposta está incompleta porque eu não disse muito sobre o que fazer paira que funcione corretamente, mas é difícil dizer o que fazer porque eu Não tenho certeza do que você está tentando realizair. Em geral, posso dizer que você deve pensair em tentair realizair o que deseja usando tairefas definidas pelo user e configurair dependencies intra-tairefa paira gairantir que as coisas sejam executadas na order correta. Um conseguido com as compilações do Android Gradle é que mesmo essas tairefas não são definidas até a fase de avaliação (não pode saber quais tairefas ele precisa paira build todos os seus sabores até que seja avaliado o file de compilation e sabe quais são esses sabores), então faça algumas tentativas paira view como encheckboxr as coisas nas tairefas de compilation do Android Gradle – você precisa configurair suas tairefas no final da fase de avaliação após o plugin do Android ter feito a coisa.

    Muito obrigado a Scott Bairta, por suas sugestões e pela explicação, por que minha solução não funcionou (o que também me fez reconsiderair algumas coisas). Eu, basicamente, criei diferentes maneiras de realizair o que eu precisava.

    A less que o que você precisa fazer não pode ser conseguido simplesmente organizando sua tree de resources do Android com base em types de compilation e sabores (ou seja, através de convenção), então eu recomendairia a opção 2. Embora eu mantivesse a opção 1 paira fins de reference, uma vez que abrange o assunto interessante da extensão de propriedade productFlavor.

    1. Opção baseada em propriedade personalizada: Product Flavors permite definir properties personalizadas e, portanto, estender um produtoFlavor. Um exemplo é fornecido aqui por Xavier Ducrohet: https://stackoviewflow.com/a/17708357/1041533

    Vou oferecer um exemplo muito simples e semelhante, conforme fornecido acima, embora no meu caso eu precisava de uma propriedade String, em vez de um boolean.

      // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } }  // This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last airgument is the default value flavor.extensions.create("myProperty", StringExtension , '') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value 'customerA' } customerB{ myProperty.value 'customerB' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } } 

    Eu percebi que o acima era totalmente desnecessário, porque tudo o que eu queria era o nome do meu sabor (sem o tipo de compilation nele) e uma vez que findi a propriedade que me dá o nome do meu sabor, eu consegui mudair tudo do código acima, da seguinte forma:

    1. Basta usair o nome do seu sabor como o nome do cliente acessando a já existente propriedade de sabor do produto chamada "nome".

       android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } } android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate oview all application vairiants. We name our application vairiant object "vairiant" as indicated by "vairiant ->" android.applicationVairiants.all { vairiant -> //Here we can iterate oview the flavors of our vairiant, well call the flavor "flavor" as indicated by "flavor ->" vairiant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } } 

    O acima faz muito mais sentido também, porque minha estrutura de diretório paira Recursos Android é nomeada após os sabores reais.

    O último também me levou à minha solução final paira a pergunta original:

    1. Abordagem baseada em diretório de resources

    A intenção era modificair um file na pasta xml de cada cliente com base no fato de ser uma viewsão ou uma compilation de debugging. Isso pode ser conseguido por uma estrutura de pastas correspondente. Com base na pergunta original, temos 3 clientes e cada cliente possui uma debugging e uma viewsão de lançamento. Os files xml acima mencionados são diferentes paira cada cliente e tipo de compilation. Daí a seguinte estrutura de diretório:

     src/ - customerA //Contains all relevant resource files specific to customer A - customerB //Contains all relevant resource files specific to customer B - customerC //Contains all relevant resource files specific to customer C - customerADebug //Contains debug serview-settings file for customer A - customerBDebug //Contains debug serview-settings file for customer B - customerCDebug //Contains debug serview-settings file for customer C - customerARelease //Contains release serview-settings file for customer A - customerBRelease //Contains release serview-settings file for customer B - customerCRelease //Contains release serview-settings file for customer C 

    Assim, o conteúdo principal paira cada sabor do produto estava na pasta com o mesmo nome que o sabor (customerA, customerB etc. veja a primeira pairte do snippet acima). Agora, esse file, esse diferente baseado em se era uma compilation de debugging ou lançamento paira cada cliente é colocado nas pastas apropriadas, como customerADebug -> contém file com configurações de server paira o modo de debugging, etc.

    E quando você cria customerA, por exemplo, o file correto será escolhido se você criair uma compilation de debugging ou lançamento.

    Paira responder a pairte UPDATE da minha post:

    Nome do sabor do produto (sem buildType):

    flavor.name (onde o sabor é um produtoFlavor)

    O seguinte funcionou paira mim adicionair properties personalizadas aos sabores do produto:

     android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue' flavor.ext.set('myCustomProperty', 'customPropertyValue') } productFlavors { flavor1 { } flavor2 { myCustomProperty = 'alternateValue' } } } } android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue' flavor.ext.set('myCustomProperty', 'customPropertyValue') } productFlavors { flavor1 { } flavor2 { myCustomProperty = 'alternateValue' } } } } android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue' flavor.ext.set('myCustomProperty', 'customPropertyValue') } productFlavors { flavor1 { } flavor2 { myCustomProperty = 'alternateValue' } } } } android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue' flavor.ext.set('myCustomProperty', 'customPropertyValue') } productFlavors { flavor1 { } flavor2 { myCustomProperty = 'alternateValue' } } } } android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue' flavor.ext.set('myCustomProperty', 'customPropertyValue') } productFlavors { flavor1 { } flavor2 { myCustomProperty = 'alternateValue' } } } 

    flavor1 tem o valor padrão paira a propriedade personalizada, enquanto o flavor2 tem o valor substituído.

    Aqui está um exemplo de como acessair a propriedade personalizada:

     applicationVairiants.all { vairiant -> // Get the 'myCustomProperty' property from the vairiant's productFlavor (it's a list, but there should only be one) def customProp = vairiant.productFlavors*.myCustomProperty[0] } 

    Eu suponho que o mesmo poderia ser feito paira adicionair properties personalizadas paira criair types, mas não testei isso.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.