2013-06-24 13 views
14

Ho creato una nuova app con gradle in Android Studio e ora ho bisogno di fare circa 10 versioni con nomi di pacchetti e valori diversi nelle risorse. Ho creato aromi personalizzati come nell'esempio e desidero sostituire alcune stringhe in questi gusti personalizzati con valori personalizzati. Ho trovato esempio come questo:Come sostituire le risorse di stringhe con Android Gradle

filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: ['version': '2.2']) 

Ma non so dove metterlo. Come ho capito ho bisogno di metterlo in attività separate, ma come rendere questa attività chiamata da IDE?

Inoltre ho bisogno di sostituire alcune variabili all'interno delle classi Java e dell'autenticazione del provider di contenuti, forse ho bisogno di farlo copiando i file nella cartella flavor1 e lasciamo gradle per unirlo, ma sembra una soluzione sbagliata per archiviare molte copie di file con differenza in una riga ... Forse ho bisogno di usare qualche altra soluzione per tutto questo?

Ecco build.gradle:

buildscript { 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.4.2' 
    } 
} 
apply plugin: 'android' 

dependencies { 
    compile fileTree(dir: 'libs', include: '*.jar') 
    compile project(':JazzyListView') 
    compile project(':ABS') 
    compile project(':Volley') 
} 

android { 
    compileSdkVersion 17 
    buildToolsVersion "17.0.0" 

    defaultConfig { 
     versionCode 5 
     versionName "3.0" 
     minSdkVersion 8 
     targetSdkVersion 17 
    } 

    sourceSets { 
     main { 
      manifest.srcFile 'src/main/AndroidManifest.xml' 
      java.srcDirs = ['src/main/java'] 
      res.srcDirs = ['src/main/res'] 
     } 
    } 

    productFlavors { 
     flavor1 { 
      packageName "com.example.flavor1"    
     } 

     flavor2 { 
      packageName "com.example.flavor2" 
     } 

    } 

} 

risposta

2

Nella cartella "src", creare "flavor1" e cartelle "flavor2" con la stessa gerarchia come la cartella "principale". Se hai strings.xml nei tuoi valori principali/res /, puoi farlo anche in flavor1/res/values ​​e avere i valori di sostituzione lì. Potrebbe mostrare errori nell'IDE, ma dovrebbe comunque essere compilato ed eseguito.

1

Questi link possono essere utili:

E la mia definizione del filtro usando espressioni regolari per sostituire qualcosa:

from('res/') { 
    include '**/*.xml' 
    filter { 
     line -> line.replaceAll(/YOUR_REGEX_TO_REPLACE_SOMETHING/, 'REPLACED_RESULT_EXPRESSION') 
    } 
} 
into 'build/path/to/your/filtered/resources/' 
+2

Grazie, ma come definire questo compito e come usarlo nel tipo di costruzione o il sapore? – itspers

+0

@itspers Vedere la mia risposta per maggiori informazioni su come modificare una specifica variante di build – goldierox

+0

il problema è dove si trova il percorso '' build/percorso/to/tuo/filtrato/risorse/' ' – aelam

18

Ho avuto un problema simile. Volevo aggiungere il numero di build di Jenkins alle stringhe che vengono unite da strings.xml. Ecco la mia soluzione di Android Gradle plug-in 0.12. +.

// Insert the build number into strings.xml 
android.applicationVariants.all{ variant -> 
    variant.mergeResources.doLast{ 
     ext.env = System.getenv() 
     def buildNumber = env.BUILD_NUMBER 
     if (buildNumber != null) { 
      File valuesFile = file("${buildDir}/intermediates/res/${variant.dirName}/values/values.xml") 
      println("Replacing revision number in " + valuesFile) 
      println("Build number = " + buildNumber) 
      String content = valuesFile.getText('UTF-8') 
      content = content.replaceAll(/devBuild/, buildNumber) 
      valuesFile.write(content, 'UTF-8') 
     } 
    } 
} 

È possibile eseguire il hook in un'attività Gradle diversa in base a ciò che si desidera eseguire. Dai un'occhiata ai compiti che fanno parte della build di Android per capirlo.

http://tools.android.com/tech-docs/new-build-system/user-guide

UPDATE: Ad un certo punto, il plugin Gradle Android ha cambiato il modo per scorrere attraverso l'applicazione varianti parola chiave da ogni-tutto. La mia risposta è stata aggiornata per riflettere la modifica, ma prova a passare a ogni se questo codice non stampa nulla sulla console.

+1

Ho un dubbio che ho ricercato la struttura delle cartelle, in '$ {buildDir}' c'è una cartella 'rs' nella cartella' source' 'e una' res', dubito che siano simili, ma perché la 'fonte/rs' è vuoto, sebbene ("$ {buildDir}/res/all/$ {variant.dirName} /values/values.xml") 'può risolvere il problema ma che ne dici di modificare un valore-14.xml? – aelam

+0

@aelam, credo che la directory 'rs' sia per RenderScript, mentre la cartella' res' è per le tue risorse. Se si volesse modificare un file "values- [API-level] .xml", si potrebbe probabilmente usare un'espressione regolare o iterare attraverso i file in quella directory. Non so come non essere in cima alla mia testa. Consiglierei di dare un'occhiata alla documentazione di Gradle. http://www.gradle.org/docs/current/userguide/working_with_files.html – goldierox

+1

Sono riuscito a farlo funzionare in 0.8 con: File valuesFile = new File ("$ {buildDir}/intermedi/res/$ {variante. dirName} /values/values.xml ") ma richiede innanzitutto una pulizia gradlew, cercando una soluzione migliore. – eski

4

Stavo cercando di ottenere funzionalità simili a quelle del filtraggio delle risorse Maven. Questo è quello che mi è venuto in mente. La mia soluzione potrebbe utilizzare alcune modifiche per essere più robuste (cioè estrarre da un file di proprietà, ecc.).

Il mio esempio mostra solo come sostituire un singolo valore, che è tutto ciò di cui avevo bisogno. Le variabili seguono la convenzione ${some.property}. Questa soluzione funziona anche con i sapori del prodotto che hanno i loro file di risorse.

import org.apache.tools.ant.filters.* 
... 
android.applicationVariants.all{ variant -> 
    // Perform resource filtering 
    variant.mergeResources.doLast { 
     filterResources(variant) 
    } 
} 

def filterResources(buildVariant) { 

    //Setup temp directory to filter the resources 
    File resFiltered = file("${buildDir}/res/all/filtered/${buildVariant.dirName}") 
    if(resFiltered.exists()){ 
     resFiltered.delete() 
    } 

    //Copy and filter the resources. 
    copy { 
     from(buildVariant.processResources.resDir) { 
      include '**/*.xml' 

      //Could be improved upon to pull from a properties file, etc. 
      ant.properties['app.version'] = project.version 

      filter(ExpandProperties, project: ant.project) 

     } 
     from(buildVariant.processResources.resDir) { 
      exclude '**/*.xml' 
     } 

     into resFiltered 

    } 

    //Delete all the original resource files 
    file(buildVariant.processResources.resDir).deleteDir() 
    //Replace with the filtered ones. 
    resFiltered.renameTo(file(buildVariant.processResources.resDir)) 
    //Delete the original 'filtered' directory 
    file("${buildDir}/res/all/filtered").deleteDir() 
} 

Esempio in strings.xml

... 
<string name="app_version">${app.version}</string> 
... 
+0

Ciao ho qualche problema con l'implementazione di questo, ottengo l'eccezione: Esecuzione fallita per task ': app: mergeDebugResources'. > Nessuna proprietà: ExpandProperties per la classe: org.gradle.api.internal.file.copy.CopySpecWrapper_Decorated. Sai cosa farne? – Billda

+0

quale versione di gradle stai usando? –

+0

Questo non funziona con AAPT2 perché i file .xml sono appiattiti prima di essere scritti sul disco. Vedi: https://issuetracker.google.com/issues/65220623 –

Problemi correlati