Android: varias versiones personalizadas de la misma aplicación

¿Cuál es la mejor manera de implementar varias versiones personalizadas de una aplicación de Android?

Actualmente tengo un script para intercambiar la carpeta de recursos para obtener una versión personalizada de mi aplicación. Funciona muy bien, pero todas las versiones personalizadas tienen el mismo nombre de paquete en AndroidManifest.xml. Por lo tanto, no es posible instalar dos versiones personalizadas de la aplicación al mismo tiempo.

Esta es una solución para este problema, pero que tiene que hacerse a mano

¿Puede usted pensar en una solución más fácil, o cómo esto podría ser incorporado en un skript?

(BTW: no es para un porn / spam / cualquier aplicación, ni siquiera un pago)

Tal vez el built-in Android "biblioteca" concepto no fue totalmente al horno en el momento de la publicación original, pero puede ser el método preferido a partir de 2011. Siga estos pasos para una hormiga de construcción:

A partir de una aplicación de trabajo (vamos a llamar directorio "myOrigApp", paquete com.foo.myapp), sólo tiene que añadir esta línea a "default.properties" para que sea una biblioteca:

 android.library=true 

Ahora crea una nueva aplicación en un directorio de hermanos de la manera que prefieras (llamémoslo directorio "hermano", paquete com.foo.myVariant). Usando Intellij Idea, por ejemplo, cree un proyecto 'desde cero' con el directorio 'sibling' y creará todos los archivos / directorios que normalmente necesitaría.

En ese nuevo directorio de hermanos, edite "default.properties" para agregar la dependencia:

 android.library.reference.1=../myOrigApp 

Copia del Manifiesto desde el directorio original:

 cd sibling cp ../myOrigApp/AndroidManifest.xml ../myOrigApp/local.properties ../myOrigApp/build.properties . 

Edite ese archivo Manifest copiado para cambiar su nombre de paquete a su nueva variante, "com.foo.myVarient"; Ese es el único cambio.

Si acaba de ejecutar los scripts de construcción de hormigas, se puede hacer. (Tuve que configurar las teclas de firma.)

Si desea configurar un IDE como Idea para tener el proyecto de biblioteca como dependiente del proyecto variante, siga estos pasos para agregar un proyecto de biblioteca al proyecto variante (asume que ya tiene un proyecto configurado para ambos):

  • Abra el proyecto original, abra Configuración del proyecto, seleccione su faceta y marque "Es proyecto de biblioteca" y guarde.
  • Abra el proyecto de la variante, abra la Configuración del proyecto, seleccione Módulos
  • Añadir un módulo
  • Seleccione "Importar módulo existente"
  • Vaya al directorio Original (myOrigApp) y seleccione su archivo .iml (archivo de origen del proyecto IntelliJ)
  • Haga clic en "Finalizar". (El proyecto de biblioteca se agrega como un módulo dentro del proyecto variante.)
  • En la lista de módulos haga clic sobre el proyecto Variant para seleccionarlo.
  • En el lado derecho seleccione la pestaña "Dependencias".
  • Haga clic en "Agregar …"
  • Elija "Dependency module …" (Debe aparecer una lista que incluya el nombre del módulo / biblioteca que agregó previamente al proyecto, tal vez la única entrada en la lista).
  • Seleccione el proyecto de biblioteca que ha agregado y pulse Aceptar. (Se agregará a la lista de dependencias de su proyecto.)
  • Pulse OK para finalizar la configuración del proyecto. (Debería ver 2 módulos, con los recursos y clases de la biblioteca disponibles y reconocidos en el proyecto Variant.)

Lo que hice para algo similar a esto es simplemente utilizar una tarea antlib y luego pasar por todos los archivos java y xml para reemplazar mi cadena de paquete antiguo a la nueva cadena de paquete. No importaba si los archivos no estaban en las rutas de origen correctas de acuerdo con el paquete. Sólo hacer un reemplazo regex para todos los archivos fue suficiente para mí para conseguir este trabajo …

Por ejemplo, para reemplazarlo en todos sus archivos java en el directorio src:

  <replaceregexp flags="g" byline="false"> <regexp pattern="old.package.string" /> <substitution expression="new.package.string" /> <fileset dir="src" includes="**/*.java" /> </replaceregexp> 

Definitivamente desea utilizar sabores Gradle que viene de forma nativa, incluso alentado, en Android Studio.

Parece explicar todo lo básico muy bien. Acabo de terminar de convertir a Gradle hoy, y funciona muy bien. Iconos, nombres y cadenas de aplicaciones personalizadas, etc.

Como explica el sitio web, parte del propósito detrás de este diseño era hacerlo más dinámico y permitir más fácilmente que se crearan múltiples APKs con esencialmente el mismo código, lo que suena similar a lo que estás haciendo.

Probablemente no lo explique lo mejor, pero ese sitio web hace un buen trabajo.

La solución enlazada no tiene que ser hecha a mano. Tenga en cuenta que el atributo del package en el elemento <manifest> no tiene que estar donde reside el código, siempre y cuando especifique las clases totalmente calificadas en otro lugar del manifiesto (por ejemplo, activity android:name="com.commonsware.android.MyActivity" lugar de la activity android:name=".MyActivity" ). Escriba su cambio de manifiesto y utilice Ant para crear un nuevo APK. AFAIK, eso debería funcionar.

Soporte de varios socios Prepare config.xml

Construir proyecto para diferentes socios

 <!--partner.dir, pkg.name, ver.code, ver.name are input from command line when execute 'ant' --> <!-- set global properties for this build --> <property name="build.bin" location="bin"/> <property name="build.gen" location="gen"/> <property name="src" location="src"/> <property name="res" location="res"/> <target name="preparefiles" description="Prepare files for different partner" > <delete dir="${build.bin}" /> <delete dir="${build.gen}" /> <copy todir="${res}" overwrite="true" /> <fileset dir="${partner.dir}/res" /> </copy> <!-- change the import in all Java source files --> <replaceregexp file="AndroidManifest.xml" match='android.versionCode="(.*)"' replace='android.versionCode="${ver.code}"' byline="false"> <replaceregexp file="AndroidManifest.xml" match='android.versionName="(.*)"' replace='android.versionName="${ver.name}"' byline="false"> <replaceregexp file="AndroidManifest.xml" match='package="(.*)"' replace='package="${pkg.name}"' byline="false"> <!-- change the package name in AndroidManifest --> <replaceregexp flags="g" byline="false"> <regexp pattern="import(.*)com.myproject.com.R;" /> <substitution expression="import com.${pkg.name}.R;" /> <fileset dir="${src}" includes="**/*.java" /> </replaceregexp> <replaceregexp flags="g" byline="false"> <regexp pattern="(package com.myproject.com;)" /> <substitution expression="\1&#10;import com.${pkg.name}.R;" /> <fileset dir="${src}" includes="**/*.java" /> </replaceregexp> </target> 

Preparar archivos $ ant -f config.xml -Dpartner.dir = "xxx" -Dpkg.name = "xxx" -Dver.code = "xxx" -Dver.name = "xxx" preparefiles

Crear build.xml Crear $ ant debug o $ ant release

Estoy usando el maven-android-plugin para lograr esto. Especifique un AndroidManifest.xml para el objetivo de fuentes generadas y otro AndroidManifest.xml para el objetivo final de apk. De esta manera, el proyecto de código fuente conserva el nombre del paquete de código fuente real durante la generación de la clase R y la fase de compilación, mientras que el nombre del paquete de manifiesto adaptado al mercado se encuentra en el segundo AndroidManifest.xml incluido en el archivo apk final.

Terminé con un guión que remendaba las fuentes; Remendar la fuente suena arriesgado, pero en presencia de control de versión el riesgo es aceptable.

Así que hice una versión, confirmó la fuente, hizo la otra versión, confirmó la fuente, y mirando diffs escribió un script de parche en Python.

No estoy seguro si es la mejor solución. (Y el código pierde algunos ospath.joins)

El corazón de la secuencia de comandos es la siguiente función:

 # 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,mandatory=True): with open(fname, 'r+') as f: read_data = f.read() pattern = r"("+re.escape(before)+r")\w+("+re.escape(after)+r")" replacement = r"\1"+newtext+r"\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 "",")" elif replacements_made: print fname,":" print new_data elif mandatory: raise Exception("cannot patch the file: "+fname) 

Y usted puede encontrar el siguiente de uso:

 # Change the application resource package name everywhere in the src/ tree. # Yes, this changes the java files. We hope that if something goes wrong, # the version control will save us. def patchResourcePackageNameInSrc(pname): for root, dirs, files in os.walk('src'): if '.svn' in dirs: dirs.remove('.svn') for fname in files: fileReplace(os.path.join(root,fname),"import com.xyz.",pname,".R;",mandatory=False) 

También hay una función que copia los activos de x-assets-cfgname a los assets (antes resultó que para mí es más conveniente tener un subdirectorio en los assets ).

 def copyAssets(vname,force=False): assets_source = "x-assets-"+vname+"/xxx" assets_target = "assets/xxx" if not os.path.exists(assets_source): raise Exception("Invalid variant name: "+vname+" (the assets directory "+assets_source+" does not exist)") if os.path.exists(assets_target+"/.svn"): raise Exception("The assets directory must not be under version control! "+assets_target+"/.svn exists!") if os.path.exists(assets_target): shutil.rmtree(assets_target) shutil.copytree(assets_source, assets_target, ignore=shutil.ignore_patterns('.svn')) 

Bueno, ya captas la idea. Ahora puedes escribir tu propio guión.

Creo que la mejor manera es crear un nuevo proyecto y copiar el material. – crear un nuevo proyecto android sin una clase – crear un paquete (el nombre del paquete debe corresponder al archivo del manifiesto), o simplemente copiar el nombre del paquete en la carpeta 'gen' – copiar los archivos java – copiar las carpetas dibujables – copiar los archivos de diseño – copiar cualquier otro archivo utilizado en el proyecto ur – copiar los datos del archivo de manifiesto

Esto ha sido más fácil para mí para la tarea

  • Cómo cambiar la orientación del dispositivo Android con ADB
  • ¿Cómo probar la conexión wifi vía adb?
  • Appium: Cómo iniciar la aplicación de Android para el perfil de trabajo
  • Automatizar el proceso de publicación de la aplicación para Android
  • "Si cada teléfono responde a OK Google ",
  • Automatice la implementación en la Consola para programadores de Android
  • Android, Error = No se puede encontrar la información de instrumentación para: ComponentInfo {}
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.