Cómo descompilar y compilar APKs

De HTCMania Wiki

Voy a intentar explicar como descompilar y luego volver a compilar un APK de Android, después de haber hecho modificaciones tanto en los ficheros XML como en los PNG.

Como ejemplo vamos a descompilar el framework-res.apk y vamos a modificar los xml para que podamos poner la batería que queramos.

Contenido

¿Que es compilar?

De manera muy sencilla es traducir un lenguaje de programación a otro lenguaje, en nuestro caso al lenguaje que entiende Android. Lógicamente descompilar es traducir el lenguaje que utiliza Android a uno que nosotros podamos entender.

¿Que hacen los ficheros XML?

En este caso, el de la batería, son los que gestionan cuando tiene que cambiar el icono para que lo veamos en la pantalla. Con el framework original, el icono la batería solo cambia en intervalos del 20% aproximadamente (luego lo vemos con más detalle), lo que vamos a intentar hacer es modificar-lo para que varíe en intervalos del 1%. Si se descomprime el framework-res.apk e intentáis abrir los XML con un editor de textos vereis como os dice que tururu, que no entiende nada, por eso es necesario descompilar.

Descompilar

Primero necesitamos una herramienta para hacerlo, en XDA podemos encontrar una aplicación llamada APKManager, que tiene versiones tanto para Windows como para Linux y sirve para muchas cosas más que compilar.

Descargamos la versión que queramos y la descomprimimos en la carpeta que queramos (vamos a hacerlo en el escritorio) y renombramos la carpeta descomprimida a apkmanager (esto no es necesario lo hacemos para aclararnos todos con el manual).

Una vez descomprimida vemos que dentro de la carpeta apkmanager tenemos varias carpetas mas y un fichero:

  • other: Contiene los scripts necesarios para lo que vamos a hacer (no la tocamos).
  • place-apk-here-for-modding: Aquí vamos a poner el framework-res.apk.
  • place-apk-here-for-signing: Para firmar el APK (si sólo vamos a firmarla).
  • pace-apk-here-to-batch-optimize: Para optimizar las imágenes y por tanto el uso de RAM.
  • Script: Fichero que ejecuta el programa.

(En Windows también tenemos las carpetas place-ogg-here y projects)

Iniciamos el apkmanager:

  • Para Linux:
    • Abrimos un terminal
cd Escritorio/apkmanager
./Script.sh
  • Para Windows:
    • Inicio → Ejecutar → cmd
cd Escritorio/apkmanager
script

Primero nos pregunta si queremos borrar los archivos que hay en las carpetas del apkmanager si no tenemos nada poner que N y si hay algo y queréis borrarlo pues Y, pulsamos Intro y nos aparece una pantalla como esta:

pantallaapkmanager.png

Cogemos nuestro framework-res.apk que vamos a modificar y lo colocamos en la carpeta place-apk-here-for-modding

Seleccionamos la opción 9-Decompile apk y voilá tenemos nuestro APK descompilado en una carpeta que se ha creado en la carpeta apkmanager que se llama out.

El primer problema que nos vamos a encontrar es saber que fichero es el que tenemos que modificar, normalmente por el nombre se puede saber cual es, si no lo encontramos buscamos y si con estas tampoco pues preguntamos. En nuestro caso veremos que para cambiar la batería tenemos que modificar 3 ficheros XML, estos son: stat_sys_battery.xml, stat_sys_battery_charge.xml y zzz_stat_sys_battery_1.xml. El primero y el último nos indican el estado de carga de la batería en uso y el segundo el estado cuando se está cargando.

Para abrir los XML, podemos usar cualquier editor de textos (recomendable NotePad++ porque no introduce caracteres extraños), si abrimos por ejemplo stat_sys_battery.xml (está en la carpeta drawable) nos encontramos que pone lo siguiente:

<?xml version="1.0" encoding="UTF-8"?> 
<level-list 
  xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/stat_sys_battery_0" android:maxLevel="4" /> 
    <item android:drawable="@drawable/stat_sys_battery_10" android:maxLevel="14" /> 
    <item android:drawable="@drawable/stat_sys_battery_20" android:maxLevel="29" /> 
    <item android:drawable="@drawable/stat_sys_battery_40" android:maxLevel="49" /> 
    <item android:drawable="@drawable/stat_sys_battery_60" android:maxLevel="69" /> 
    <item android:drawable="@drawable/stat_sys_battery_80" android:maxLevel="89" /> 
    <item android:drawable="@drawable/stat_sys_battery_100" android:maxLevel="100" /> 
</level-list>

Ahora vamos a cambiar lo que nosotros queremos y es que cambie cada 1%, tendremos que escribir en ese fichero lo siguiente:

<?xml version="1.0" encoding="UTF-8"?> 
<level-list 
  xmlns:android="http://schemas.android.com/apk/res/android"> 
   <item android:drawable="@drawable/stat_sys_battery_0" android:maxLevel="0" />
   <item android:drawable="@drawable/stat_sys_battery_1" android:maxLevel="1" />
   <item android:drawable="@drawable/stat_sys_battery_2" android:maxLevel="2" />
   <item android:drawable="@drawable/stat_sys_battery_3" android:maxLevel="3" />
   <item android:drawable="@drawable/stat_sys_battery_4" android:maxLevel="4" />
   <item android:drawable="@drawable/stat_sys_battery_5" android:maxLevel="5" />
   <item android:drawable="@drawable/stat_sys_battery_6" android:maxLevel="6" />
   <item android:drawable="@drawable/stat_sys_battery_7" android:maxLevel="7" />
   <item android:drawable="@drawable/stat_sys_battery_8" android:maxLevel="8" />
   <item android:drawable="@drawable/stat_sys_battery_9" android:maxLevel="9" />
   <item android:drawable="@drawable/stat_sys_battery_10" android:maxLevel="10" />
   <item android:drawable="@drawable/stat_sys_battery_11" android:maxLevel="11" />
   <item android:drawable="@drawable/stat_sys_battery_12" android:maxLevel="12" />
   <item android:drawable="@drawable/stat_sys_battery_13" android:maxLevel="13" />
   <item android:drawable="@drawable/stat_sys_battery_14" android:maxLevel="14" />
   <item android:drawable="@drawable/stat_sys_battery_15" android:maxLevel="15" />
   <item android:drawable="@drawable/stat_sys_battery_16" android:maxLevel="16" />
   <item android:drawable="@drawable/stat_sys_battery_17" android:maxLevel="17" />
   <item android:drawable="@drawable/stat_sys_battery_18" android:maxLevel="18" />
   <item android:drawable="@drawable/stat_sys_battery_19" android:maxLevel="19" />
   <item android:drawable="@drawable/stat_sys_battery_20" android:maxLevel="20" />
   <item android:drawable="@drawable/stat_sys_battery_21" android:maxLevel="21" />
   <item android:drawable="@drawable/stat_sys_battery_22" android:maxLevel="22" />
   <item android:drawable="@drawable/stat_sys_battery_23" android:maxLevel="23" />
   <item android:drawable="@drawable/stat_sys_battery_24" android:maxLevel="24" />
   <item android:drawable="@drawable/stat_sys_battery_25" android:maxLevel="25" />
   <item android:drawable="@drawable/stat_sys_battery_26" android:maxLevel="26" />
   <item android:drawable="@drawable/stat_sys_battery_27" android:maxLevel="27" />
   <item android:drawable="@drawable/stat_sys_battery_28" android:maxLevel="28" />
   <item android:drawable="@drawable/stat_sys_battery_29" android:maxLevel="29" />
   <item android:drawable="@drawable/stat_sys_battery_30" android:maxLevel="30" />
   <item android:drawable="@drawable/stat_sys_battery_31" android:maxLevel="31" />
   <item android:drawable="@drawable/stat_sys_battery_32" android:maxLevel="32" />
   <item android:drawable="@drawable/stat_sys_battery_33" android:maxLevel="33" />
   <item android:drawable="@drawable/stat_sys_battery_34" android:maxLevel="34" />
   <item android:drawable="@drawable/stat_sys_battery_35" android:maxLevel="35" />
   <item android:drawable="@drawable/stat_sys_battery_36" android:maxLevel="36" />
   <item android:drawable="@drawable/stat_sys_battery_37" android:maxLevel="37" />
   <item android:drawable="@drawable/stat_sys_battery_38" android:maxLevel="38" />
   <item android:drawable="@drawable/stat_sys_battery_39" android:maxLevel="39" />
   <item android:drawable="@drawable/stat_sys_battery_40" android:maxLevel="40" />
   <item android:drawable="@drawable/stat_sys_battery_41" android:maxLevel="41" />
   <item android:drawable="@drawable/stat_sys_battery_42" android:maxLevel="42" />
   <item android:drawable="@drawable/stat_sys_battery_43" android:maxLevel="43" />
   <item android:drawable="@drawable/stat_sys_battery_44" android:maxLevel="44" />
   <item android:drawable="@drawable/stat_sys_battery_45" android:maxLevel="45" />
   <item android:drawable="@drawable/stat_sys_battery_46" android:maxLevel="46" />
   <item android:drawable="@drawable/stat_sys_battery_47" android:maxLevel="47" />
   <item android:drawable="@drawable/stat_sys_battery_48" android:maxLevel="48" />
   <item android:drawable="@drawable/stat_sys_battery_49" android:maxLevel="49" />
   <item android:drawable="@drawable/stat_sys_battery_50" android:maxLevel="50" />
   <item android:drawable="@drawable/stat_sys_battery_51" android:maxLevel="51" />
   <item android:drawable="@drawable/stat_sys_battery_52" android:maxLevel="52" />
   <item android:drawable="@drawable/stat_sys_battery_53" android:maxLevel="53" />
   <item android:drawable="@drawable/stat_sys_battery_54" android:maxLevel="54" />
   <item android:drawable="@drawable/stat_sys_battery_55" android:maxLevel="55" />
   <item android:drawable="@drawable/stat_sys_battery_56" android:maxLevel="56" />
   <item android:drawable="@drawable/stat_sys_battery_57" android:maxLevel="57" />
   <item android:drawable="@drawable/stat_sys_battery_58" android:maxLevel="58" />
   <item android:drawable="@drawable/stat_sys_battery_59" android:maxLevel="59" />
   <item android:drawable="@drawable/stat_sys_battery_60" android:maxLevel="60" />
   <item android:drawable="@drawable/stat_sys_battery_61" android:maxLevel="61" />
   <item android:drawable="@drawable/stat_sys_battery_62" android:maxLevel="62" />
   <item android:drawable="@drawable/stat_sys_battery_63" android:maxLevel="63" />
   <item android:drawable="@drawable/stat_sys_battery_64" android:maxLevel="64" />
   <item android:drawable="@drawable/stat_sys_battery_65" android:maxLevel="65" />
   <item android:drawable="@drawable/stat_sys_battery_66" android:maxLevel="66" />
   <item android:drawable="@drawable/stat_sys_battery_67" android:maxLevel="67" />
   <item android:drawable="@drawable/stat_sys_battery_68" android:maxLevel="68" />
   <item android:drawable="@drawable/stat_sys_battery_69" android:maxLevel="69" />
   <item android:drawable="@drawable/stat_sys_battery_70" android:maxLevel="70" />
   <item android:drawable="@drawable/stat_sys_battery_71" android:maxLevel="71" />
   <item android:drawable="@drawable/stat_sys_battery_72" android:maxLevel="72" />
   <item android:drawable="@drawable/stat_sys_battery_73" android:maxLevel="73" />
   <item android:drawable="@drawable/stat_sys_battery_74" android:maxLevel="74" />
   <item android:drawable="@drawable/stat_sys_battery_75" android:maxLevel="75" />
   <item android:drawable="@drawable/stat_sys_battery_76" android:maxLevel="76" />
   <item android:drawable="@drawable/stat_sys_battery_77" android:maxLevel="77" />
   <item android:drawable="@drawable/stat_sys_battery_78" android:maxLevel="78" />
   <item android:drawable="@drawable/stat_sys_battery_79" android:maxLevel="79" />
   <item android:drawable="@drawable/stat_sys_battery_80" android:maxLevel="80" />
   <item android:drawable="@drawable/stat_sys_battery_81" android:maxLevel="81" />
   <item android:drawable="@drawable/stat_sys_battery_82" android:maxLevel="82" />
   <item android:drawable="@drawable/stat_sys_battery_83" android:maxLevel="83" />
   <item android:drawable="@drawable/stat_sys_battery_84" android:maxLevel="84" />
   <item android:drawable="@drawable/stat_sys_battery_85" android:maxLevel="85" />
   <item android:drawable="@drawable/stat_sys_battery_86" android:maxLevel="86" />
   <item android:drawable="@drawable/stat_sys_battery_87" android:maxLevel="87" />
   <item android:drawable="@drawable/stat_sys_battery_88" android:maxLevel="88" />
   <item android:drawable="@drawable/stat_sys_battery_89" android:maxLevel="89" />
   <item android:drawable="@drawable/stat_sys_battery_90" android:maxLevel="90" />
   <item android:drawable="@drawable/stat_sys_battery_91" android:maxLevel="91" />
   <item android:drawable="@drawable/stat_sys_battery_92" android:maxLevel="92" />
   <item android:drawable="@drawable/stat_sys_battery_93" android:maxLevel="93" />
   <item android:drawable="@drawable/stat_sys_battery_94" android:maxLevel="94" />
   <item android:drawable="@drawable/stat_sys_battery_95" android:maxLevel="95" />
   <item android:drawable="@drawable/stat_sys_battery_96" android:maxLevel="96" />
   <item android:drawable="@drawable/stat_sys_battery_97" android:maxLevel="97" />
   <item android:drawable="@drawable/stat_sys_battery_98" android:maxLevel="98" />
   <item android:drawable="@drawable/stat_sys_battery_99" android:maxLevel="99" />
   <item android:drawable="@drawable/stat_sys_battery_100" android:maxLevel="100" />
 </level-list>

Como esto es un rollo y en muchas ocasiones ya tenemos el XML modificado, lo que haremos es sustituir los ficheros unos por otros sin tener que editar el XML. Ahora bien si quisiéramos que la batería cambiara en intervalos del 5% podemos editarlo y adaptarlo a lo que queremos.

Una vez hemos terminado con los XML tenemos que sustituir o añadir los iconos necesarios para cumplir con todas las referencia que hemos añadido o modificado en los XML. Para esto es interesante abrir los XML y observar cuales son los ficheros que tenemos que tener.

Compilamos

Una vez añadido todo tenemos que compilar. Para ello en el script (que no hemos cerrado) seleccionamos la opción 10-Compile apk, tras unos segundos el programa nos creara un APK en la carpeta place-apk-here-for-modding llamada repackaged-unsigned.apk.

Firmamos

Si queremos firmarla seleccionamos la opción 11-Sign apk, veremos que el fichero cambia de nombre a repackaged-signed.apk.

Ya tenemos nuestra APK firmada, sólo nos queda renombrarla a framework-res.apk.

Para flashearla la ponemos en un ZIP, lo firmamos y lo flasheamos.


Descompilar un APK con dependencias usando APKTool

Esxisten algunos ficheros apk que no podremos descompilar usando el método explicado anteriormente ya que de por si esos ficheros dependen de otros. Es el caso de HtcContacts.apk que depende del fichero com.htc.resources.apk


Un método para hacerlo que a mí me ha funcionado es utilizar una herramienta llamada apktool, esta es la página del proyecto apktool instalar según se explica.

Método:

1- Nos creamos una carpeta donde copiamos el HtcContacts.apk que queremos descompilar, por ejemplo Escritorio/Contactos.

2- Conectamos el telefono al ordenador

3- Extraemos el com.htc.resources.apk en la carpeta creada anteriormente

adb remount
adb pull /system/framework/com.htc.resources.apk /home/usuario/Escritorio/Contactos

Con esto ya tenemos los dos ficheros en nuestra carpeta

4- Abrimos un terminal, (linea de comandos en windows)

cd Escritorio/Contactos
apktool if com.htc.resources.apk
apktool d HtcContacts.apk

Ya tenemos descompilado el fichero en una carpeta que nos ha creado llamado HtcContacts

5- Para compilar una vez modificado

cd Escritorio/Contactos
apktool b HtcContacts

Nos crea el apk en la carpeta “dist” dentro de HtcContacts

Ojo porque el apk que crea no está firmado y por tanto no tiene la carpeta META-INF, debemos firmarlo por ejemplo con el ApkManager (opción 15 en la versión Linux)

Ejemplos prediseñados

Batería en formato %

  • Nombre: stat_sys_batery.xml, stat_sys_battery_charge.xml y zzz_stat_sys_battery_1.xml
  • Descarga: http://www.megaupload.com/?d=NZO2X62K
  • APK: framework-res.apk
  • Ubicación: res/drawable/
  • Información: Modifica los intervalos de actualización de la batería, 100 imagenes para carga y 20 imagenes para descarga.

GPS animado

  • Nombre: stat_sys_gps_acquiring_anim.xml
  • Descarga: http://www.megaupload.com/?d=2RY744YE
  • APK: framework-res.apk
  • Ubicación: res/drawable/
  • Información: Anima el icono mientras el GPS esta conectando

Sincronización animada

  • Nombre: stat_notify_sync_anim0.xml
  • Descarga: http://www.megaupload.com/?d=T8M7QQTQ
  • APK: framework-res.apk
  • Ubicación: res/drawable/
  • Información: Modifica los intervalos de actualización de la batería
  • ZIP de ejemplo: La estructura completa de lo que hay que modificar para ese MOD.

Videotutoriales

Cambiando imágenes

Cambiando la barra de estado

Cambiando las fuentes del sistema

Como editar los .9.png

Herramientas personales