Tengo 2 sabores de construcción, digamos, sabor1 y sabor2 .
Me gustaría que mi aplicación se llamara, digamos, " AppFlavor1 " cuando construyo para el sabor1 y " AppFlavor2 " cuando construyo para el sabor 2.
No es el título de las actividades que quiero cambiar. Quiero cambiar el nombre de la aplicación como se muestra en el menú del teléfono y en otros lugares.
Desde build.gradlepuedo establecer varios parámetros para mis sabores pero, al parecer, no la etiqueta de la aplicación. Y tampoco puedo cambiar la etiqueta de la aplicación mediante programación en función de alguna variable.
Entonces, ¿cómo maneja la gente esto?

sourceSetsbloque? ¿Está debajo delandroid{...}bloque?androidcuadra de hecho.Eliminar
app_namedestrings.xml(de lo contrario, gradle se quejará de recursos duplicados). Luego modifique el archivo de compilación de esta manera:productFlavors { flavor1{ resValue "string", "app_name", "AppNameFlavor1" } flavor2{ resValue "string", "app_name", "AppNameFlavor2" } }También asegúrese de
@string/app_nameque se asigne un valor para elandroid:labelatributo en el manifiesto.<application ... android:label="@string/app_name" ...Esto es menos perturbador que crear nuevos
strings.xmlen diferentes conjuntos construidos o escribir scripts personalizados.fuente
@string/app_namepara tuactivityetiqueta de lanzador ? Tenga en cuenta que ellabeldel lanzador principalactivityse usa con preferencia al del nombreapplicationlabelpara mostrar de la aplicación.Si desea mantener la localización del nombre de la aplicación en diferentes sabores, puede lograrlo de la siguiente manera:
1) Especificar
android:labelen<application>disponible enAndroidManifest.xmlla siguiente forma:<application ... android:label="${appLabel}" ... >2) Especifique el valor predeterminado fo
appLabelen el nivel de la aplicaciónbuild.gradle:manifestPlaceholders = [appLabel:"@string/defaultName"]3) Anule el valor de los sabores de los productos de la siguiente manera:
productFlavors { AppFlavor1 { manifestPlaceholders = [appLabel:"@string/flavor1"] } AppFlavor2 { manifestPlaceholders = [appLabel:"@string/flavor2"] } }4) Agregue recursos de cadena para cada una de las cadenas (nombre predeterminado, sabor1, sabor2) en su
strings.xml. Esto le permitirá localizarlos.fuente
Puede agregar un archivo de recursos de cadenas a cada sabor y luego usar esos archivos de recursos para cambiar el nombre de su aplicación. Por ejemplo, en una de mis aplicaciones, tengo una versión gratuita y de pago. Para renombrarlos "Lite" y "Pro", creé un
meta_data.xmlarchivo, agregué miapp_namevalor a ese XML y lo eliminé destrings.xml. A continuación,app/srccree una carpeta para cada sabor (consulte a continuación la estructura de ejemplo). Dentro de estos directorios, agregueres/values/<string resource file name>. Ahora, cuando compile, este archivo se copiará en su compilación y su aplicación cambiará de nombre.Estructura de archivo:
app/src /pro/res/values/meta_data.xml /lite/res/values/meta_data.xmlfuente
Otra opción que realmente utilizo es cambiar el manifiesto para cada aplicación. En lugar de copiar la carpeta de recursos, puede crear un manifiesto para cada sabor.
sourceSets { main { } release { manifest.srcFile 'src/release/AndroidManifest.xml' } debug { manifest.srcFile 'src/debug/AndroidManifest.xml' } }Debe tener un AndroidManifest principal en su src main que será el principal. Luego puede definir un manifiesto con solo algunas opciones para cada sabor como (src / release / AndroidManifest.xml):
<manifest package="com.application.yourapp"> <application android:icon="@drawable/ic_launcher"> </application> </manifest>Para la depuración, AndroidManifest (src / debug / AndroidManifest.xml):
<manifest package="com.application.yourapp"> <application android:icon="@drawable/ic_launcher2"> </application> </manifest>El compilador fusionará el manifiesto y puede tener un icono para cada sabor.
fuente
Esto se puede lograr fácilmente en 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 } }Solo asegúrese de eliminar app_name de strings.xml
fuente
En primer lugar, responda esta pregunta: "¿Puede el usuario instalar ambos tipos de su aplicación en el mismo dispositivo?"
Utilizo un script de Python que parchea la fuente. Contiene algunas funciones reutilizables y, por supuesto, conocimiento de lo que se necesita parchear en este proyecto en particular. Entonces, el script es específico de la aplicación.
Hay muchos parches, los datos para parchear se guardan en un diccionario de Python (incluidos los nombres de los paquetes de aplicaciones, por cierto, son diferentes del nombre del paquete de Java), un diccionario por sabor.
En cuanto a l10n, las cadenas pueden apuntar a otras cadenas, por ejemplo, en mi código tengo:
<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>fuente
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Después de limpiar y reconstruir todo (dos veces, una por sabor), debe obtener dos apk-s con diferentes nombres de paquetes de Android y diferentes etiquetas de inicio. Por cierto, Eclipse a menudo no detecta cambios en los recursos, por lo que debe pedirle que limpie.Sin embargo, ¿cómo puedo hacer que string / app_name sea diferente por sabor?
Quería escribir una actualización, pero me di cuenta de que es más grande que la respuesta original que dice que uso un script de Python que parchea la fuente.
La secuencia de comandos de Python tiene un parámetro, un nombre de directorio. Ese directorio contiene activos por sabor, recursos como íconos de iniciador y el archivo properties.txt con un diccionario de Python.
{ 'someBoolean' : True , 'someParam' : 'none' , 'appTitle' : '@string/x_app_name_xyz' }La secuencia de comandos de Python carga el diccionario desde ese archivo y reemplaza el valor entre
<string name="app_name">y</string>por el valor deproperties['appTitle'].El siguiente código se proporciona tal cual está / como estaba, etc.
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_/@\- ]+")para leer las propiedades de uno o más de estos archivos:
with open(filename1) as f: properties = eval(f.read()) with open(filename2) as f: properties.update(eval(f.read()))y la función fileReplace es:
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+"'")Las primeras líneas del guión son:
#!/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 copytreeoverfuente
En el archivo AndroidManifest, en la etiqueta de la aplicación tienes esta línea:
android:labelY allí puede decir cómo aparecerá la etiqueta de la aplicación en el menú de aplicaciones del dispositivo
fuente