2016-02-08 18 views
9

Vorrei poter caricare il valore di stringhe visibili dall'utente da res/values ​​/ strings.xml dal nostro CMS (o qualche DB), durante la build del gradle.In una build gradle Android, modifica il contenuto di strings.xml durante la compilazione

E.g.

<string name="button_label">OK, do it</string> 

potrebbe essere cambiato al

<string name="button_label">OK, do it now!</string> 

... o qualsiasi altra cosa.

L'idea è che il nuovo valore verrà letto AL BUILD TIME dal nostro CMS e quindi verrà inserito nel file APK. (La motivazione è di automatizzare le modifiche alle stringhe delle app, in modo che qualsiasi testo dall'app venga letto da un CMS esistente).

Qual è il modo migliore per raggiungere questo obiettivo? È possibile generare/modificare i file di risorse (ad es. Strings.xml) durante la compilazione, prima che vengano utilizzati dal sistema di build di Android?


l'aggiunta di alcuni altri requisiti:

+1

il modo semplice: http://tools.android.com/tech-docs/new-build-system variant.resValue ... altro: crea il proprio plugin gradle ... – Selvin

+0

Grazie Selvin, sembra promettente. Una domanda su questo però: come potrei fare per fornire valori di fallback per diverse lingue? È possibile con questa funzione? – treesAreEverywhere

+0

'applicationVariants.all {variant -> variant.resValue" string "," button_xxx "," Qui va il testo "}' ... ovviamente è necessario imparare alcune nozioni di base di Groovy (ad esempio per ottenere quei valori online o da il tuo specifico file xml/json) ... fx https://gist.github.com/SelvinPL/f89476b6585690cb252b ... io lo uso per generare fx 'colorPrimaryAX' che è colorPrimary con X% alpha https: //gist.github .com/SelvinPL/8e673e38c5fed8e2132b – Selvin

risposta

3

Ecco una soluzione in cui le stringhe vengono modificate tramite un file di proprietà esterno. Non sono sicuro che questo soddisfi esattamente il tuo requisito, ma dovrebbe portarti all'inizio.

Faccio qualcosa di simile nelle mie build: ho alcune attività gradle personalizzate con questo tipo di sostituzione chiamato all'interno del loro doFirst(). L'espressione regolare qui potrebbe probabilmente usare un po 'di lucidatura, e il formato di input potrebbe cambiare in base alle tue esigenze, ma in alcuni test locali questo sembra funzionare per me.

ext.updateStrings = { 
println("Changing strings!") 
Properties props = new Properties() 
props.load(new FileInputStream(file('cms.properties'))) 
def stringsFile = file("src/main/res/values/strings.xml") 
def stringsText = stringsFile.getText() 
for (p in props) { 
    def pattern = Pattern.compile(String.format("%s\">.*<", p.key)); 
    def match = pattern.matcher(stringsText); 
    match.find(); 
    println("found key " + p.key + ", replacing string with " + p.value) 
    stringsText = match.replaceAll(String.format("%s\">%s<", p.key, p.value)) 
    stringsFile.write(stringsText) 
    } 
} 

Conservo le mie proprietà/funzioni esterne in un file separato (ad esempio common.gradle). Nella tua build.gradle, si potrebbe aggiungere un'attività personalizzata in questo modo:

apply from: "common.gradle" 
task updateStringsXml() { 
    doFirst { 
     updateStrings() 
    } 
} 

Poi, il comando Gradle potrebbe essere simile gradle updateStringsXml assembleRelease.

+0

La parte interessante è ... come si integra questo nel processo di compilazione, anche se hai diversi sapori/buildTypes, oltre a ignorare la lingua? – treesAreEverywhere

+0

Vedere la mia modifica - come per i tipi di sapori/build, è possibile aggiungere facilmente le proprietà del progetto e modificare in modo condizionale le stringhe in questo modo. Mi piace usarli come descritto [qui] (http://stackoverflow.com/questions/11696521/how-to-pass-arguments-from-command-line-to-gradle). Lo stesso vale per le lingue, i tuoi "cms.properties" potrebbero contenere qualsiasi lingua tu voglia. – lase