Nomi di app diversi per gusti di build diversi?


94

Ho 2 gusti di costruzione, diciamo, sapore1 e sapore2 .

Vorrei che la mia applicazione fosse denominata, ad esempio, " AppFlavor1 " quando creo per flavour1 e " AppFlavor2 " quando creo per flavour 2.

Non è il titolo delle attività che voglio cambiare. Desidero modificare il nome dell'app così come viene visualizzato nel menu del telefono e altrove.

Da build.gradleposso impostare vari parametri per i miei gusti ma, a quanto pare, non l'etichetta dell'app. E non posso cambiare anche l'etichetta dell'app a livello di programmazione in base a qualche variabile.

Allora, come lo gestiscono le persone?

Risposte:


24

Invece di cambiare il tuo principale strings.xml con uno script e rischiare di rovinare il tuo controllo del codice sorgente, perché non fare affidamento sul comportamento di fusione standard della build Android Gradle?

Il mio build.gradlecontiene

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }

    release {
        res.srcDir 'variants/release/res'
    }

    debug {
        res.srcDir 'variants/debug/res'
    }
}

Quindi ora posso definire la mia app_namestringa nel file variants/[release|debug]/res/strings.xml. E anche qualsiasi altra cosa che voglio cambiare!


Modificato: usa res.srcDir per aggiungere all'array invece di ridefinirlo del tutto.
Pierre-Luc Paour

Sì, ormai l'ho capito anch'io. Grazie mille
Alexander Kulyakhtin

1
Dove si dovrebbe aggiungere il sourceSetsblocco? È sotto il android{...}blocco?
Abel Callejo

@AbelMelquiadesCallejo all'interno del androidblocco davvero.
Pierre-Luc Paour

261

Rimuovi app_nameda strings.xml(altrimenti gradle si lamenterà di risorse duplicate). Quindi modifica il file di build in questo modo:

productFlavors {
    flavor1{
        resValue "string", "app_name", "AppNameFlavor1"
    }

    flavor2{
        resValue "string", "app_name", "AppNameFlavor2"
    }
   } 

Assicurati anche che il @string/app_namevalore sia assegnato android:labelall'attributo nel manifest.

<application
        ...
        android:label="@string/app_name"
        ...

Questo è meno dirompente rispetto alla creazione di nuovi strings.xmlin set costruiti diversi o alla scrittura di script personalizzati.


9
Funziona come un fascino, ma domanda: come aggiungiamo stringhe localizzate per altre impostazioni locali quando aggiungiamo la risorsa stringa in questo modo?
AndroidMechanic - Viral Patel

pubblicato una domanda per questo qui: stackoverflow.com/questions/36105494/… Ti dispiace dare un'occhiata per favore?
AndroidMechanic - Viral Patel

3
Che ne dici di utilizzare più dimensioni di sapore? Come posso denominarlo in modo diverso per ciascuna combinazione di sapore / sapore?
Zocket

1
Va tutto bene, ma il nome dell'app mostrato sotto l'icona di avvio non cambia come impostato dal gusto del prodotto gradle. Ho rimosso "app_name" da strings.xml e ho impostato l'aroma del prodotto. Se vedo il nome dell'app dalla pagina Informazioni sull'app di Android, che mostra il nome dell'app impostato in base al gusto del prodotto, ma sotto l'icona di avvio che mostra il nome dell'app precedente.
iamcrypticcoder

2
@ mahbub.kuet stai usando @string/app_nameper la tua activityetichetta di avvio ? Tieni presente che il labeldal programma di avvio principale activityviene utilizzato di preferenza application labelper il nome visualizzato dell'app.
user650881

13

Se desideri mantenere la localizzazione per il nome dell'app in diversi gusti, puoi ottenerla come segue:

1) Specificare android:labelin <application>disponibile AndroidManifest.xmlcome segue:

<application
    ...
    android:label="${appLabel}"
    ...
>

2) Specifica il valore predefinito per il appLabellivello di app build.gradle:

manifestPlaceholders = [appLabel:"@string/defaultName"]

3) Sostituisci il valore per gli aromi del prodotto come segue:

productFlavors {
    AppFlavor1 {
        manifestPlaceholders = [appLabel:"@string/flavor1"]
    }
    AppFlavor2 {
        manifestPlaceholders = [appLabel:"@string/flavor2"]
    }

}

4) Aggiungi risorse stringa per ciascuna delle stringhe (defaultName, flavour1, flavour2) nel tuo file strings.xml. Questo ti permetterà di localizzarli.


Il passaggio 2 deve essere nel livello "defaultConfig" di build.gradle NON nel livello "android", altrimenti riceverai un errore di proprietà sconosciuto relativo al nome manifestPlaceholder.
Brendon Whateley

8

Puoi aggiungere un file di risorse di stringhe a ogni gusto, quindi utilizzare quei file di risorse per cambiare il nome dell'app. Ad esempio in una delle mie app, ho una versione gratuita e una a pagamento. Per rinominarli "Lite" e "Pro", ho creato un meta_data.xmlfile e ho aggiunto il mio app_namevalore a tale XML e l'ho rimosso da strings.xml. Successivamente, app/srccrea una cartella per ogni gusto (vedi sotto per esempio la struttura). All'interno di queste directory, aggiungi res/values/<string resource file name>. Ora, quando crei, questo file verrà copiato nella tua build e la tua app verrà rinominata.

Struttura del file:

app/src
   /pro/res/values/meta_data.xml
   /lite/res/values/meta_data.xml

1
Questo è meglio che dichiarare in un file gradle. Funziona come un fascino. Grazie.
Filip Luchianenco

7

Un'altra opzione che utilizzo effettivamente è modificare il manifest per ciascuna applicazione. Invece di copiare la cartella delle risorse, puoi creare un manifest per ogni gusto.

sourceSets {
  main {
 }

  release {
    manifest.srcFile 'src/release/AndroidManifest.xml'
 }

  debug {
    manifest.srcFile 'src/debug/AndroidManifest.xml'
 }
}

Devi avere un AndroidManifest principale nel tuo src main che sarà il principale. Quindi puoi definire un manifest con solo alcune opzioni per ogni gusto come (src / release / AndroidManifest.xml):

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher">
  </application>
</manifest>

Per il debug, AndroidManifest (src / debug / AndroidManifest.xml):

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher2">
  </application>
</manifest>

Il compilatore farà un'unione del manifest e puoi avere un'icona per ogni gusto.


4

Questo può essere facilmente ottenuto con buildTypes

buildTypes {
    debug {
        buildConfigField("String", "server_type", "\"TEST\"")
        resValue "string", "app_name", "Eventful-Test"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    stage {
        buildConfigField("String", "server_type", "\"STAGE\"")
        resValue "string", "app_name", "Eventful-Stage"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    release {
        buildConfigField("String", "server_type", "\"PROD\"")
        resValue "string", "app_name", "Eventful"
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        //TODO - add release signing
    }
}

Assicurati solo di rimuovere app_name da strings.xml


2

Prima di tutto, rispondi a questa domanda: "L'utente può installare entrambe le versioni della tua applicazione sullo stesso dispositivo?"

Uso uno script Python che patcha il sorgente. Contiene alcune funzioni riutilizzabili e, ovviamente, la conoscenza di ciò che deve essere corretto in questo particolare progetto. Quindi lo script è specifico dell'applicazione.

C'è un sacco di patch, i dati per l'applicazione sono conservati in un dizionario Python (inclusi i nomi dei pacchetti dell'applicazione, a proposito sono diversi dal nome del pacchetto Java), un dizionario per gusto.

Per quanto riguarda l10n, le stringhe possono puntare ad altre stringhe, ad esempio nel mio codice ho:

<string name="app_name">@string/x_app_name_xyz</string>

<string name="x_app_name_default">My Application</string>
<string name="x_app_name_xyz">My App</string>

È una specie di versioni Light vs Pro, penso che l'utente possa averle entrambe
Alexander Kulyakhtin

Quindi dovrai cambiare il nome del pacchetto dell'app, ad esempio com.example.mysoft.pro vs com.example.mysoft.light , altrimenti l'utente sarà in grado di installarne solo uno sullo stesso dispositivo.
18446744073709551615

L'ho fatto, ma come faccio a ottenere "La mia app" e "La mia app Pro" nel menu del telefono? Ora ho 2 app (light e pro) ma entrambe hanno lo stesso nome. Ho bisogno di 2 nomi di app distinti per questo e, come stai dicendo, non è così facile?
Alexander Kulyakhtin

Come menziona l'altra risposta (downvoted), in AndroidManifest.xml c'è <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Dopo aver pulito e ricostruito tutto (due volte, una volta per gusto), dovresti ottenere due apk con diversi nomi di pacchetti Android e diverse etichette di avvio. A proposito, Eclipse spesso non rileva i cambiamenti nelle risorse, quindi devi chiedergli di pulire.
18446744073709551615

Tuttavia, come faccio a rendere la stringa / nome_app diverso in base al gusto? Mi dispiace di non riuscire ancora a capirlo.
Alexander Kulyakhtin

0

Tuttavia, come faccio a rendere la stringa / nome_app diverso in base al gusto?

Volevo scrivere un aggiornamento, ma mi sono reso conto che è più grande della risposta originale dicendo che uso uno script Python che patcha il sorgente.

Lo script Python ha un parametro, un nome di directory. Quella directory contiene risorse per gusto, risorse come icone di avvio e il file properties.txt con un dizionario Python.

{ 'someBoolean' : True
, 'someParam' : 'none'
, 'appTitle' : '@string/x_app_name_xyz'
}

Lo script Python carica il dizionario da quel file e sostituisce il valore compreso tra <string name="app_name">e </string>con il valore di properties['appTitle'].

Il codice seguente viene fornito così com'è / così com'era ecc.

for strings_xml in glob.glob("res/values*/strings.xml"):
    fileReplace(strings_xml,'<string name="app_name">',properties['appTitle'],'</string>',oldtextpattern=r"[a-zA-Z0-9_/@\- ]+")

per leggere le proprietà da uno o più di questi file:

with open(filename1) as f:
    properties = eval(f.read())
with open(filename2) as f:
    properties.update(eval(f.read()))

e la funzione fileReplace è:

really = True
#False for debugging

# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,oldtextpattern=r"[\w.]+",mandatory=True):
    with open(fname, 'r+') as f:
        read_data = f.read()
        pattern = r"("+re.escape(before)+r")"+oldtextpattern+"("+re.escape(after)+r")"
        replacement = r"\g<1>"+newtext+r"\g<2>"
        new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
        if replacements_made and really:
            f.seek(0)
            f.truncate()
            f.write(new_data)
            if verbose:
                print "patching ",fname," (",replacements_made," occurrence" + ("s" if 1!=replacements_made else ""),")",newtext,("-- no changes" if new_data==read_data else "-- ***CHANGED***")
        elif replacements_made:
            print fname,":"
            print new_data
        elif mandatory:
            raise Exception("cannot patch the file: "+fname+" with ["+newtext+"] instead of '"+before+"{"+oldtextpattern+"}"+after+"'")

Le prime righe dello script sono:

#!/usr/bin/python
# coding: utf-8

import sys
import os
import re
import os.path
import shutil
import argparse
import string
import glob
from myutils import copytreeover

-4

Nel file AndroidManifest, nel tag dell'applicazione hai questa riga:

android:label

E lì puoi dire come apparirà l'etichetta dell'applicazione nel menu delle applicazioni sul dispositivo


Sì, ho letto la domanda ... Puoi impostare 2 rami e per ognuno (uno per flavour1 e uno per flavour2) impostare un'etichetta android: diversa nel tuo file AndroidManifest.
Hitman

6
Ah, non lo sapevo. Ma come inserisco quei 2 file manifest? Anche se non è possibile
Alexander Kulyakhtin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.