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.gradle
puedo 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?
sourceSets
bloque? ¿Está debajo delandroid{...}
bloque?android
cuadra de hecho.Eliminar
app_name
destrings.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_name
que se asigne un valor para elandroid:label
atributo en el manifiesto.<application ... android:label="@string/app_name" ...
Esto es menos perturbador que crear nuevos
strings.xml
en diferentes conjuntos construidos o escribir scripts personalizados.fuente
@string/app_name
para tuactivity
etiqueta de lanzador ? Tenga en cuenta que ellabel
del lanzador principalactivity
se usa con preferencia al del nombreapplication
label
para 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:label
en<application>
disponible enAndroidManifest.xml
la siguiente forma:<application ... android:label="${appLabel}" ... >
2) Especifique el valor predeterminado fo
appLabel
en 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.xml
archivo, agregué miapp_name
valor a ese XML y lo eliminé destrings.xml
. A continuación,app/src
cree 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.xml
fuente
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 copytreeover
fuente
En el archivo AndroidManifest, en la etiqueta de la aplicación tienes esta línea:
android:label
Y allí puede decir cómo aparecerá la etiqueta de la aplicación en el menú de aplicaciones del dispositivo
fuente