2012-05-13 12 views
14

Estoy trabajando en un proyecto de código abierto. Como se pretende que cualquiera pueda descargar la fuente y compilarla, no quiero codificar el nombre del paquete en ningún lado, incluida la estructura del directorio.Android - ¿Cómo configuro dinámicamente el nombre del paquete en tiempo de compilación para un proyecto de código abierto?

Yo uso ant para la construcción. Aparentemente puedo modificar build.xml, pero creo que esto es sobrescrito por android update. Lo que sea que se use estará comprometido con el repositorio de Git, y no debería ser demasiado complicado.

Actualmente, el proceso para construir el código directamente desde el repositorio Git es bastante simple. He aquí un extracto del archivo README:

$ cd ~/src/isokeys/IsoKeys 
$ android list targets # I build against API level 10. 
$ android update project --name IsoKeys --target 1 --path ./ # Only needed first time. 
$ ant debug && adb -d install -r bin/IsoKeys-debug.apk 

Para mí, tiene sentido para poner el nombre del paquete en local.properties, porque este es .gitignore 'd. Como el nombre del paquete no estará en ningún otro lado, la construcción fallará sin hacer esto. Por lo tanto, debe haber al menos 1 paso adicional en el README, pero quiero mantenerlo al mínimo.

Editar: Por supuesto, otro requisito es que las diferenciaciones tienen sentido - que no lo hacen si cambia el nombre manualmente el nombre del paquete.

+0

Esto parece bastante tonto. No he oído hablar de ningún proyecto de código abierto que salte a través de aros como este. –

+1

Los dos motivos principales son que los diffs para un directorio renombrado son un problema, y ​​que este y muchos otros proyectos de código abierto no tienen su propio dominio sino que están alojados en un sitio de alojamiento de código como sourceforge.net, etc. y los tenedores/fusiones son comunes. –

Respuesta

20

Hice algo similar (pero no por esta razón) que requirió actualizar el manifiesto en tiempo de compilación. La forma en que logré esto fue haciendo un segundo AndroidManifest y colocándolo bajo un directorio llamado config. Así en config/AndroidManifest que podría tener algo como esto:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="@[email protected]" 
     android:versionCode="@[email protected]" 
     android:versionName="@[email protected]"> 


<!-- EVERYTHING ELSE GOES HERE --> 


</manifest> 

continuación, puede utilizar el esqueleto regulares hormiga build.xml la escritura con sólo unas pocas modificaciones (sin necesidad de copiar el guión completo de la compilación de Android sistema ya que agregaron algunos ganchos para que los use sin reinventar la rueda). La escritura de la estructura debe estar leyendo local.properties por defecto, pero si no añade (o descomentar) una línea como esta:

<property file="local.properties" /> 

En su escritura de la estructura se debe ver una tarea llamada "-preparaciones de acumulación", cambiará como sigue:

<target name="-pre-build"> 
    <copy file="config/AndroidManifest.xml" todir="." overwrite="true" encoding="utf-8"> 
     <filterset> 
      <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" /> 
      <filter token="CONFIG.APP_VERSION" value="${app.version}" /> 
      <filter token="CONFIG.APP_VERSION_CODE" value="${app.versioncode}" /> 
     </filterset> 
    </copy>   
</target> 

luego presentar sus local.properties que pondría el nombre del paquete, la versión del nombre/código de este modo:

app.version=1.0 
app.versioncode=1 
app.packagename=com.mypackage.name 

Ahora sólo tiene que asegurarse de que en y nuestro manifiesto de que usted califica completamente todas sus actividades/servicios/oyentes de difusión, etc. Eso significa que siempre especifica el paquete completo de su código fuente. Si quieres que el paquete para tu propio código fuente sea dinámico, puedes reemplazar cada uno de los prefijos de cada clase ... Pero parece algo tonto. Es bastante fácil empaquetar tu código bajo tu propio nombre de paquete y puede usarlo desde cualquier proyecto simplemente incluyendo la fuente o un contenedor en su proyecto.

- ACTUALIZACIÓN - Ah, y una cosa que puede hacer para notificar al usuario que debe definir un nombre de paquete es utilizar la etiqueta de fallar en su estructura XML como esto:

<fail message="app.packagename is missing. This must be defined in your local.properties file" unless="app.packagename" /> 

poner esto después de la línea que dice el local.archivo de propiedades

+0

Ah, mi script de compilación (generado por la actualización de Android), _is_ 'barebones' y contiene ''. Entonces puedo enviar este archivo al repositorio con algunas modificaciones. Bien, déjame ver ... –

+0

Sí, algunas personas dicen que es una mala idea, pero lo he estado haciendo durante más de un año sin problemas. Es obvio que dejas esos ganchos para ti, pero no hay ninguna garantía de que en la próxima versión de Android puedan cambiar las cosas. IIRC la otra cosa que tenía que hacer para jugar bien con Eclipse era agregar: Sin embargo, para los cambios anteriores no deberían necesitar esto. Solo lo necesitaba para poder reutilizar algunos de los objetivos en las herramientas/ant/build.xml de mi script, y para hacerlo solo tenía que usar androidbuild. [Nombre de destino] –

+0

Si no tenía el La sección "as = androidbuild" luego eclipse se quejaría de que los objetivos no existían y eclipse no lograría construir mi proyecto a pesar de que en primer lugar no estaba usando mi script ant de eclipse. –

6

Gracias a Matt Wolfe por su ayuda, estoy publicando una respuesta parcial con mis esfuerzos hasta el momento.

me di cuenta de que el defecto Barebones build.xml También habría importar custom_rules.xml:

<import file="custom_rules.xml" optional="true" /> 

Así que creó el archivo y empezó a juguetear. Esto es lo que he encontrado hasta el momento:

<?xml version="1.0" encoding="UTF-8"?> 
<project name="custom_rules" default="debug"> 
    <target name="-pre-build"> 
     <fail message="Please define app.packagename in your local.properties file." unless="app.packagename" /> 
     <taskdef resource="net/sf/antcontrib/antcontrib.properties"> 
      <classpath> 
       <pathelement location="/usr/share/java/ant-contrib.jar"/> 
      </classpath> 
     </taskdef> 
     <!-- How do I check for propertyregex? 
     <fail message="Depends on ant-contrib's propertyregex for app.packagename.path." unless="propertyregex" /> 
     --> 
     <propertyregex property="app.packagename.path" 
      input="${app.packagename}/" 
      regexp="\." 
      replace="/" 
      global="true" 
     /> 
     <copy todir="build/" overwrite="true" encoding="utf-8"> 
      <fileset dir="./"> 
       <include name="AndroidManifest.xml" /> 
       <include name="res/**" /> 
       <include name="lib/**" /> 
      </fileset> 
      <filterset> 
       <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" /> 
      </filterset> 
     </copy> 
     <copy todir="build/src/${app.packagename.path}" overwrite="true" encoding="utf-8"> 
      <fileset dir="./src/isokeys/"> 
       <include name="**" /> 
      </fileset> 
      <filterset> 
       <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" /> 
      </filterset> 
     </copy> 
    </target> 
    <target name="-pre-clean" description="Removes output files created by -pre-build."> 
     <delete file="build/AndroidManifest.xml" verbose="${verbose}" /> 
     <delete dir="build/res/" verbose="${verbose}" /> 
     <delete dir="build/lib/" verbose="${verbose}" /> 
     <delete dir="build/src/" verbose="${verbose}" /> 
    </target> 
    <!-- NOW CHANGE DIRECTORY TO build/ BEFORE HANDING BACK OVER TO build.xml!!! --> 
</project> 

Esto pone todo en build/(que tiene la ventaja añadida de mantener las cosas limpias y ordenadas), ahora la intención es que las herramientas de SDK build.xml a ejecutar desde este directorio build/. Sin embargo, no puedo encontrar ninguna forma de cd 'ing.

+0

Hasta ahora solo hay un paso adicional para el 'README', lo cual es una buena noticia:' $ echo 'app.packagename = your.package.name' >> local.properties' –

+0

Recomendaría agregar esto al final como estaba obteniendo un error int en el build xml. Esto porque la tarea if de Android requiere el elemento , mientras que la tarea ant-contrib if no lo admite. Como no podemos cambiar los archivos de compilación de Android y debemos cumplirlos, nos vemos obligados a utilizar la tarea if de Android en todos los lugares Jack

+0

cómo cambiar el directorio a construir/ ? – Jason

1

La manera más fácil podría ser reemplazar el nombre del paquete lo más tarde posible. De esta manera, ni siquiera tiene que tocar su código. Hay un buen artículo llamado Renaming the Android Manifest package (http://www.piwai.info/renaming-android-manifest-package/). Resumen:

  • Puede utilizar aapt --rename-manifest-package para modificar el nombre del paquete

  • Alternativamente, si desea la sustitución nombre del paquete a ser parte del proceso de construcción de la hormiga, puede anular el objetivo -package-resources:

    • copiar el objetivo de -package-resources build.xml del SDK
    • añadir manifestpackage parámetro
Cuestiones relacionadas