No se pueden crear varios archivos de dex de Android con Ant desde tarros externos
quickblox antbuilder (2)
Estoy desarrollando una aplicación para Android que requiere múltiples bibliotecas (para Facebook, Google Maps v2 y Quickblox entre otras), lo que resulta en un desbordamiento de cantidad de método que supera el límite de 64K:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
Como no puedo prescindir de ninguna de esas bibliotecas, busqué una solución para el error de límite de método. Encontré una entrada de blog popular de Android Developers, donde se recomienda una división de código fuente. (La entrada del blog del que estoy hablando se puede encontrar aquí: http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html ). He estado intentando esta solución sin éxito.
El problema que tengo ahora es que la mayor cantidad de código no está en mi aplicación, sino en las bibliotecas requeridas, por lo que tengo que distribuir esas bibliotecas entre los diferentes archivos dex que debo cargar en mi aplicación. Mi conocimiento de Ant es muy limitado, y lo que me gustaría saber es lo que debo escribir en mi archivo build.xml para hacer una copia dex de cada biblioteca donde quiero:
<!-- Primary dex to include my source code and some libraries. -->
<copy todir="${out.classes.absolute.dir}.1" >
<fileset dir="${out.classes.absolute.dir}" >
...
</fileset>
</copy>
<!-- Secondary dex to include some other libraries. -->
<copy todir="${out.classes.absolute.dir}.2" >
<fileset dir="${out.classes.absolute.dir}" >
...
</fileset>
</copy>
Cualquier ayuda sería realmente apreciada. Gracias de antemano, un cordial saludo!
La mejor respuesta que he escuchado sobre este problema hasta ahora es usar ProGuard en modo optimizado (proguard-android-optimize.txt) con la bandera -dontobfuscate
para eliminar clases y métodos no utilizados de la APK final (sin ofuscarlos). Luego puede usar ProGuard mapping.txt para ayudarlo a eliminar las clases no utilizadas de los JAR de la biblioteca que usa (no conozco una buena herramienta para hacer esto). Desafortunadamente, no creo que ProGuard tenga una función para hacer esto automáticamente.
ProGuard solo se ejecuta cuando se realiza una exportación en Eclipse, no cuando se ejecuta una aplicación Ejecutar como -> Android. Esto significa que no ayudará a evitar el límite en las compilaciones de depuración, a menos que use un proceso de compilación personalizado. El creador de ProGuard sugiere usar su hermano comercial DexGuard , que se ejecutará en Eclipse en las versiones de depuración y lanzamiento.
Se recomienda encarecidamente el uso de ProGuard para las compilaciones de lanzamiento, ya que reducirá el tamaño de su código, mejorará el rendimiento (por ejemplo, al incluir el código en línea) y también ofuscará su fuente. Asegúrese de hacer suficientes pruebas en el APK final, ya que será dramáticamente diferente al de depuración. Desafortunadamente, ProGuard por sí solo no fue suficiente para resolver mi problema, así que eliminé una de mis dependencias JAR como solución alternativa.
Comprobé el número de métodos en mis JAR dependientes usando este comando:
dx --dex --output=temp.dex library.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e ''1/4 "%d/n"''
Ejemplos de números de métodos para nuestras bibliotecas más grandes:
11222 guava-11.0.1.jar
10452 aws-android-sdk-1.5.0-core.jar
5761 org.restlet.jar
5129 protobuf-java-2.4.1.jar
2499 aws-android-sdk-1.5.0-s3.jar
2024 ormlite-core-4.41.jar
1145 gson-2.2.2.jar
1716 google-http-client-1.11.0-beta.jar
Para su información, puede verificar el número de métodos en su APK utilizando dexdump (que puede encontrar en su carpeta de build-tools
SDK, por ejemplo, "Android Studio.app/sdk/build-tools/21.0.2/dexdump"):
dexdump -f MyApp.apk | grep method_ids_size
method_ids_size : 64295
En nuestro caso, solo usábamos Guava para hacer búsquedas en YouTube, por lo que fue fácil eliminar esa dependencia y darnos más espacio para respirar.
Actualización: encontré que la forma más fácil de eliminar el código no utilizado de los archivos JAR grandes era usar dex2jar en mi compilación Proguard, luego usar JD-GUI para comparar ese JAR final con el JAR de entrada específico que quería recortar. Luego elimino los paquetes de nivel superior que sé que son eliminados por Proguard. Esto me permitió eliminar> 8000 métodos de aws-android-sdk-1.5.0-core.jar.
ProGuard es una herramienta de minificación de código fuente, eliminará cualquier clase no utilizada / duplicada al empaquetar su aplicación. Entonces, incluso si está utilizando todos estos JAR externos, no utilizará el 100% de todas las clases dentro de ellos, y muchos de estos JAR podrían tener las mismas clases dentro de ellos (por ejemplo, Log4J, etc.).
Proguard está integrado en dex . Pero no se activa de forma predeterminada, tiene que ejecutar ant en modo de lanzamiento y es posible que también tenga que comentar una línea en project.properties.
Lo más probable es que ProGuard termine eliminando algunas clases utilizadas en su aplicación. Si al compilar cuando ProGuard, obtiene errores como la class X not found
, entonces configure ProGuard en proguard.cfg
que necesita esa clase:
-keep public class <full path to the class that you need>
Consulte la documentación de Android ProGuard y vea si habilitar el programa reduce el tamaño (de clases y métodos) en su APK.