dEEpEst
☣☣ In The Depths ☣☣
Staff member
Administrator
Super Moderator
Hacker
Specter
Crawler
Shadow
- Joined
- Mar 29, 2018
- Messages
- 13,861
- Solutions
- 4
- Reputation
- 32
- Reaction score
- 45,552
- Points
- 1,813
- Credits
- 55,350
7 Years of Service
56%
crear la aplicación más pequeña posible que se pueda instalar en Android 8.0 Oreo.
Nivel básico
Comencemos con la aplicación predeterminada que genera Android Studio.
, firme la aplicación y mida el tamaño del archivo en bytes con el comando stat -f%z $filename.
Luego instale el APK en el teléfono inteligente Nexus 5x en Oreo para asegurarse de que todo funcione.
Genial Nuestro APK pesa aproximadamente un megabytes y medio.
APK Analyzer
Un megabyte y medio parece demasiado grande considerando lo que hace nuestra aplicación (y no hace nada), así que examinemos el proyecto y busquemos dónde ahorrar rápidamente en el volumen. Esto es lo que generó Android Studio:
Quizás la forma más fácil de lidiar con los iconos, dado que hay un total de 15 imágenes y dos archivos XML debajo mipmap-anydpi-v26. Contemos todo esto en el
de Android Studio.
Contrariamente a nuestras suposiciones iniciales, parece que el archivo más grande es Dex, y los recursos representan solo el 20% del tamaño del APK.
Archivo
Tamaño
classes.dex
74%
res
20%
resources.arsc
4%
META-INF
2%
AndroidManifest.xml
<1%
Examinamos por separado lo que hace cada archivo.
El
archivo Dex classes.dex es el principal culpable del APK inflado, ocupa el 73% del volumen total y, por lo tanto, será el primer objetivo de la optimización. Este archivo contiene todo nuestro código compilado en formato Dex, así como una lista de métodos externos en el marco de Android y una biblioteca de soporte.
El paquete android.support enumera más de 13,000 métodos, lo que parece redundante para una aplicación como "Hello World".
Recursos
El directorio res contiene una gran cantidad de archivos de plantilla, dibujos (dibujables) y animaciones que no son visibles de inmediato en la interfaz de Android Studio. Nuevamente, se extraen de la biblioteca de soporte y ocupan aproximadamente el 20% del tamaño del APK.
El archivo resources.arsc también contiene una lista de todos estos recursos.
Firma
En la carpeta META-INFcontiene archivos CERT.SF, MANIFEST.MFy CERT.RSAque son necesarios para la
. Si un atacante cambia el código dentro del APK, las firmas no coincidirán, lo que protege al usuario de iniciar un malware extraño.
Se MANIFEST.MFenumeran los archivos del APK, y CERT.SF contiene las sumas de comprobación del manifiesto y cada archivo individual. CERT.RSA almacena la clave pública, que verifica la integridad de CERT.SF.
No hay objetivos obvios para la optimización.
AndroidManifest
AndroidManifest es muy similar a nuestro archivo original. La única diferencia es que, en lugar de recursos como cadenas y dibujos, sus identificadores enteros se indican aquí, comenzando por 0x7F.
Activar minificación
No hemos intentado activar la opción de minificación y compresión de recursos en el archivo build.gradle para nuestra aplicación. Hagámoslo
Código:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Código:
Si se establece minifyEnableden verdadero,
activa
, lo que borra la aplicación de código innecesario. También ofusca los nombres de los símbolos, lo que dificulta la ingeniería inversa de la aplicación.
shrinkResourceseliminará todos los recursos del APK que no estén directamente referenciados. Pueden surgir problemas si no accede directamente a los recursos, pero esto no se aplica a nuestra aplicación.
786 KB (disminución del 50%)
Redujimos a la mitad el tamaño del APK sin un cambio visible en el programa.
Si aún no ha incluido minifyEnabled y shrinkResources en su aplicación, esto es lo más importante que debe eliminarse de este artículo. Puede ahorrar fácilmente unos pocos megabytes si dedica un par de horas a la configuración y las pruebas.
Adiós, AppCompat, apenas reconocimos que
classes.dex ahora ocupa el 57% de todo el APK. La mayor parte de la lista de métodos del archivo Dex pertenece al paquete android.support, por lo que vamos a eliminar la biblioteca de soporte. Para hacer esto, haga lo siguiente:
108 KB (disminución del 87%)
Madre de Dios, el archivo disminuyó casi diez veces: de 786 KB a 108 KB. El único cambio notable fue solo el cambio de color de la barra de herramientas, que se convirtió en un tema predeterminado del sistema operativo.
El directorio res ahora representa el 95% del tamaño del APK debido a todos estos íconos de inicio. Si nuestro diseñador hiciera estos íconos, trataríamos de
, un formato más eficiente que es compatible con API 15 y posteriores.
Afortunadamente, Google ya ha optimizado nuestros elementos dibujables, aunque de lo contrario podríamos haberlos optimizado nosotros mismos y eliminado los metadatos no deseados de PNG utilizando
.
Hagamos algo extraordinario y reemplacemos todos nuestros íconos de inicio con un solo punto negro de un solo píxel en la carpeta res / drawable. Esta imagen pesa 67 bytes.
6808 bytes (disminución del 94%)
Eliminamos casi todos los recursos, por lo que no es sorprendente que el tamaño del APK haya disminuido en aproximadamente un 95%. Los siguientes recursos todavía se mencionan en resources.arsc:
Vamos de arriba a abajo.
Archivo de plantilla (6262 bytes, reducción del 9%)
El marco de Android
y crea automáticamente un objeto TextView, que se usa como contentView para Activity.
Intentemos prescindir de este intermediario eliminando el archivo XML y configurando contentView mediante programación. La cantidad de recursos disminuirá porque el archivo XML desaparece, pero el tamaño del archivo Dex aumentará, ya que allí mencionamos métodos adicionales de TextView.
Código:
TextView textView = new TextView(this);
textView.setText("Hello World!");
setContentView(textView);
Parece un buen intercambio.
Nombre de la aplicación (6034 bytes, reducción del 4%)
Suprima strings.xml y reemplace android: label en el manifiesto de AndroidManifest con la letra "A". Esto parece un pequeño cambio, pero eliminar la entrada de resources.arsc reduce la cantidad de caracteres en el manifiesto y elimina el archivo del directorio res. Cada pequeña cosa es buena: acabamos de guardar 228 bytes.
Icono del iniciador (5300 bytes, reducción del 13%) La
en el repositorio de la plataforma Android explica que cada recurso APK se menciona en resources.arsc con un identificador entero. Estas ID tienen dos espacios de nombres:
0x01: recursos del sistema (predefinidos en framework-res.apk)
0x7f: recursos de la aplicación (en el archivo .apk de la aplicación)
Entonces, ¿qué sucede con nuestro APK si ponemos un enlace a un recurso en el espacio de nombres 0x01? En teoría, obtendremos un ícono más hermoso y al mismo tiempo reduciremos el tamaño de nuestro archivo.
Código:
android:icon="@android:drawable/btn_star"
Por supuesto, nunca debe confiar en los recursos del sistema como iconos en una aplicación real de trabajo. Este método fallará la validación en Google Play, y algunos fabricantes también
, así que tenga cuidado.
El manifiesto (5252 bytes, reducción del 1%)
Todavía no hemos tocado el manifiesto.
Código:
android:allowBackup="true"
android:supportsRtl="true"
Eliminar estos atributos ahorra 48 bytes.
Hack Proguard (4984 bytes, reducción del 5%)
Parece que las clases BuildConfig y R aún permanecen en el archivo Dex.
Código:
-keep class com.fractalwrench.MainActivity { *; }
La refinación de la regla Proguard eliminará las clases innecesarias.
Ofuscación (4936 bytes, reducción del 1%)
Ofuscar el nombre de la clase Actividad. Para las clases regulares, Proguard lo hace automáticamente, pero como el nombre de la clase Activity se llama a través de Intents, no se ofuscó de manera predeterminada.
MainActivity -> c.java
com.fractalwrench.apkgolf -> cc
META-INF (3307 bytes, reducción del 33%)
En este momento, estamos firmando la aplicación con las firmas v1 y v2. Esto parece una pérdida de recursos, porque v2 proporciona
al hash todo el APK.
Signature v2 no es visible desde el Analizador de APK, ya que está incluido en el bloque binario en el archivo APK. La firma v1 es visible como archivos CERT.RSA y CERT.SF.
Desactivemos la firma v1 en la interfaz de Android Studio y generemos un APK firmado. Probemos y viceversa.
Firma
Tamaño
v1
3511
v2
3307
Parece que ahora usaremos v2.
Adónde vamos: no se necesita IDE.
Es hora de editar el APK manualmente. Usamos los siguientes comandos:
Código:
# 1. Создать неподписанный apk
./gradlew assembleRelease
# 2. Разархивировать архив
unzip app-release-unsigned.apk -d app
# Сделать необходимые правки
# 3. Заархивировать архив
zip -r app app.zip
# 4. Запустить zipalign
zipalign -v -p 4 app-release-unsigned.apk app-release-aligned.apk
# 5. Запустить apksigner с подписью v2
apksigner sign --v1-signing-enabled false --ks $HOME/fake.jks --out signed-release.apk app-release-unsigned.apk
# 6. Проверить подпись
apksigner verify signed-release.apk
Una descripción detallada del proceso de firma de APK está disponible
. En general, Gradle genera un archivo sin firmar, zipalign hace una alineación de bytes para recursos sin comprimir para optimizar el consumo de RAM después de cargar el APK, y al final, comienza el proceso de firma de APK criptográfico.
Un APK sin signo y sin alinear pesa 1902 bytes, lo que significa que el procedimiento agrega aproximadamente 1 kilobyte.
Tamaño de archivo no coincidente (2608 bytes, 21% de compresión)
¡Extraño! Si descomprime el APK no alineado y lo firma manualmente, el archivo META-INF / MANIFEST.MF desaparece, lo que ahorra 543 bytes. Si alguien sabe por qué sucede esto, ¡házmelo saber!
Ahora nos quedan tres archivos en el APK firmado. Pero todavía podemos deshacernos del archivo resources.arsc, ¡porque no instalamos ningún recurso!
Después de eso, solo está el archivo de manifiesto y el archivo classes.dex, ambos del mismo tamaño.
Hacks de compresión (2599 bytes, reducción en 0.5%)
Ahora cambiaremos todas las líneas restantes a 'c', actualizando las versiones a 26, y luego generaremos un APK firmado.
Código:
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "c.c"
minSdkVersion 26
targetSdkVersion 26
versionCode 26
versionName "26"
}
Código:
Esto reduce el tamaño en otros 9 bytes.
Aunque el número de caracteres en el archivo no ha cambiado, el hecho es que la frecuencia del carácter 'c' ha aumentado. Como resultado, el algoritmo de compresión funcionó de manera más eficiente.
Hola, ADB (2462 bytes, reducción del 5%)
Puede optimizar aún más el manifiesto eliminando el filtro de intento de lanzamiento para la clase de actividad. Desde este momento iniciaremos la aplicación con el siguiente comando:
Código:
adb shell am start -a android.intent.action.MAIN -n c.c/.c
Aquí está el nuevo manifiesto:
Código:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application>
<activity
android:name="c"
android:exported="true" />
</application>
</manifest>
También nos deshicimos del ícono del iniciador.
Eliminación de referencias a métodos (2179 bytes, reducción del 12%)
De acuerdo con las condiciones iniciales, debemos preparar un APK que pueda instalarse en el dispositivo.
Nuestra aplicación enumera los métodos en las clases TextView, Bundle y Activity. Puede reducir el tamaño del archivo Dex eliminando estos enlaces y reemplazándolos con la nueva clase de aplicación. Por lo tanto, el archivo Dex ahora se referirá a un único método: el constructor de la clase Aplicación.
Los archivos de origen ahora se ven así:
Código:
package c.c;
import android.app.Application;
public class c extends Application {}
Código:
Usamos adb para verificar que el APK se haya instalado correctamente, esto también se puede verificar a través de "Configuración".
Optimización de Dex (1961 bytes, reducción del 10%)
Pasé varias horas estudiando el formato de archivo Dex para esta optimización, porque diferentes mecanismos como sumas de verificación y compensaciones dificultan la edición manual.
En resumen, resultó que el único requisito para instalar el APK es el hecho de que existe el archivo classes.dex. Por lo tanto, simplemente eliminamos el archivo original, ejecutamos touch classes.dex en la consola y ahorramos el 10% del tamaño usando un archivo vacío.
A veces la solución más tonta es la mejor.
Comprensión del manifiesto (1961 bytes, reducción del 0%)
El manifiesto APK sin firmar es un archivo XML binario que parece no estar documentado oficialmente. Puede cambiar el contenido de un archivo utilizando el editor
.
Se adivinan algunos elementos interesantes en el encabezado del archivo: los primeros cuatro bytes codifican 38, que coincide con el número de versión del archivo Dex. Los siguientes dos bytes codifican 660, que coincide con el tamaño del archivo.
Intentemos eliminar un byte estableciendo targetSdkVersion en 1 y cambiando el tamaño del archivo en el encabezado a 659. Desafortunadamente, el sistema Android rechaza el nuevo archivo como un APK no válido. Parece que todo está organizado de alguna manera más complicado ...
Malentendido del manifiesto (1777 bytes, reducción del 9%)
E intente escribir caracteres aleatorios en todo el archivo y luego instale el APK sin cambiar el tamaño de archivo especificado. Esto verificará si la suma de verificación está marcada y cómo nuestros cambios afectarán las compensaciones en el encabezado del archivo.
Sorprendentemente, dicho manifiesto se percibe como un APK válido en Nexus 5X en Oreo:
Creo que acabo de escuchar al desarrollador del marco de Android responsable de apoyar BinaryXMLParser.java gritando muy fuerte en la almohada.
Para obtener el máximo beneficio, debe reemplazar todos estos caracteres tontos con bytes nulos. Esto ayudará a reconocer partes importantes del archivo en HexFiend, y también reducirá unos pocos bytes gracias al hack de compresión mencionado anteriormente. Manifiesto
UTF-8
Aquí están los componentes importantes del Manifiesto sin los cuales el APK no se instalará.
Algunas cosas son obvias, como las etiquetas de manifiesto y de paquete. En el grupo de cadenas, el código de versión y el nombre del paquete son visibles.
Manifiesto hexadecimal
Ver el archivo en hexadecimal muestra los valores en el encabezado del archivo que describen el conjunto de cadenas y otros valores, como el tamaño del archivo 0x9402. Las cadenas también están codificadas de forma interesante: si tienen más de 8 bytes, la longitud total se indica en los dos bytes anteriores.
Pero es casi imposible encontrar otras opciones de optimización aquí.
¿Ya terminaste? (1757 bytes, reducción del 1%)
Aprenderemos el APK final.
A lo largo de este nombre, el APK indicó mi nombre en la firma v2. Cree un nuevo almacén de claves que use un truco para la compresión.
Guardamos 20 bytes.
Paso 5: Reconocer
1757 bytes es muy pequeño, maldita sea. Y hasta donde yo sé, este es el APK más pequeño existente.
Sin embargo, creo razonablemente que alguien de la comunidad de Android puede realizar más optimizaciones y mejorar aún más el resultado. Si logra reducir el archivo de los 1757 bytes actuales,
donde está alojado el APK más pequeño, o
. (Desde la publicación del artículo, el archivo ya se ha reducido a 820 bytes, aproximadamente por persona).
Autor original:
2017
Nivel básico
Comencemos con la aplicación predeterminada que genera Android Studio.
This link is hidden for visitors. Please Log in or register now.
Luego instale el APK en el teléfono inteligente Nexus 5x en Oreo para asegurarse de que todo funcione.

Genial Nuestro APK pesa aproximadamente un megabytes y medio.
APK Analyzer
Un megabyte y medio parece demasiado grande considerando lo que hace nuestra aplicación (y no hace nada), así que examinemos el proyecto y busquemos dónde ahorrar rápidamente en el volumen. Esto es lo que generó Android Studio:
- MainActivity, que extiende AppCompatActivity.
- Archivo de diseño con ConstraintLayout para la ventana principal.
- Archivos de recursos con tres colores, un recurso de cadena y tema.
- Soporta bibliotecas para AppCompat y ConstraintLayout.
- Un AndroidManifest.xml.
- Archivos PNG para iconos cuadrados, redondos y de fondo.
Quizás la forma más fácil de lidiar con los iconos, dado que hay un total de 15 imágenes y dos archivos XML debajo mipmap-anydpi-v26. Contemos todo esto en el
This link is hidden for visitors. Please Log in or register now.

Contrariamente a nuestras suposiciones iniciales, parece que el archivo más grande es Dex, y los recursos representan solo el 20% del tamaño del APK.
Archivo
Tamaño
classes.dex
74%
res
20%
resources.arsc
4%
META-INF
2%
AndroidManifest.xml
<1%
Examinamos por separado lo que hace cada archivo.
El
archivo Dex classes.dex es el principal culpable del APK inflado, ocupa el 73% del volumen total y, por lo tanto, será el primer objetivo de la optimización. Este archivo contiene todo nuestro código compilado en formato Dex, así como una lista de métodos externos en el marco de Android y una biblioteca de soporte.
El paquete android.support enumera más de 13,000 métodos, lo que parece redundante para una aplicación como "Hello World".
Recursos
El directorio res contiene una gran cantidad de archivos de plantilla, dibujos (dibujables) y animaciones que no son visibles de inmediato en la interfaz de Android Studio. Nuevamente, se extraen de la biblioteca de soporte y ocupan aproximadamente el 20% del tamaño del APK.

El archivo resources.arsc también contiene una lista de todos estos recursos.
Firma
En la carpeta META-INFcontiene archivos CERT.SF, MANIFEST.MFy CERT.RSAque son necesarios para la
This link is hidden for visitors. Please Log in or register now.
Se MANIFEST.MFenumeran los archivos del APK, y CERT.SF contiene las sumas de comprobación del manifiesto y cada archivo individual. CERT.RSA almacena la clave pública, que verifica la integridad de CERT.SF.

No hay objetivos obvios para la optimización.
AndroidManifest
AndroidManifest es muy similar a nuestro archivo original. La única diferencia es que, en lugar de recursos como cadenas y dibujos, sus identificadores enteros se indican aquí, comenzando por 0x7F.
Activar minificación
No hemos intentado activar la opción de minificación y compresión de recursos en el archivo build.gradle para nuestra aplicación. Hagámoslo
Código:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Código:
Code:
-keep class com.fractalwrench.** { *; }
Si se establece minifyEnableden verdadero,
This link is hidden for visitors. Please Log in or register now.
This link is hidden for visitors. Please Log in or register now.
shrinkResourceseliminará todos los recursos del APK que no estén directamente referenciados. Pueden surgir problemas si no accede directamente a los recursos, pero esto no se aplica a nuestra aplicación.
786 KB (disminución del 50%)
Redujimos a la mitad el tamaño del APK sin un cambio visible en el programa.

Si aún no ha incluido minifyEnabled y shrinkResources en su aplicación, esto es lo más importante que debe eliminarse de este artículo. Puede ahorrar fácilmente unos pocos megabytes si dedica un par de horas a la configuración y las pruebas.
Adiós, AppCompat, apenas reconocimos que
classes.dex ahora ocupa el 57% de todo el APK. La mayor parte de la lista de métodos del archivo Dex pertenece al paquete android.support, por lo que vamos a eliminar la biblioteca de soporte. Para hacer esto, haga lo siguiente:
- Elimine completamente el bloque de dependencia de build.gradle.
Código:
dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
- Actualice MainActivity para extender la clase android.app.Activity.
Código:
Code:public class MainActivity extends Activity
- Actualice nuestra plantilla para usar un solo TextView.
Código:
Code:<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Hello World!" />
- Elimine el styles.xmlatributo View attachment 244heme de Android del elemento <application> en AndroidManifest.
- Eliminar colors.xml.
- Haz 50 flexiones mientras Gradle se sincroniza.
108 KB (disminución del 87%)
Madre de Dios, el archivo disminuyó casi diez veces: de 786 KB a 108 KB. El único cambio notable fue solo el cambio de color de la barra de herramientas, que se convirtió en un tema predeterminado del sistema operativo.

El directorio res ahora representa el 95% del tamaño del APK debido a todos estos íconos de inicio. Si nuestro diseñador hiciera estos íconos, trataríamos de
This link is hidden for visitors. Please Log in or register now.
Afortunadamente, Google ya ha optimizado nuestros elementos dibujables, aunque de lo contrario podríamos haberlos optimizado nosotros mismos y eliminado los metadatos no deseados de PNG utilizando
This link is hidden for visitors. Please Log in or register now.
Hagamos algo extraordinario y reemplacemos todos nuestros íconos de inicio con un solo punto negro de un solo píxel en la carpeta res / drawable. Esta imagen pesa 67 bytes.
6808 bytes (disminución del 94%)
Eliminamos casi todos los recursos, por lo que no es sorprendente que el tamaño del APK haya disminuido en aproximadamente un 95%. Los siguientes recursos todavía se mencionan en resources.arsc:
- 1 archivo de plantilla
- 1 recurso de cadena
- 1 icono de lanzador
Vamos de arriba a abajo.
Archivo de plantilla (6262 bytes, reducción del 9%)
El marco de Android
This link is hidden for visitors. Please Log in or register now.
Intentemos prescindir de este intermediario eliminando el archivo XML y configurando contentView mediante programación. La cantidad de recursos disminuirá porque el archivo XML desaparece, pero el tamaño del archivo Dex aumentará, ya que allí mencionamos métodos adicionales de TextView.
Código:
TextView textView = new TextView(this);
textView.setText("Hello World!");
setContentView(textView);
Parece un buen intercambio.
Nombre de la aplicación (6034 bytes, reducción del 4%)
Suprima strings.xml y reemplace android: label en el manifiesto de AndroidManifest con la letra "A". Esto parece un pequeño cambio, pero eliminar la entrada de resources.arsc reduce la cantidad de caracteres en el manifiesto y elimina el archivo del directorio res. Cada pequeña cosa es buena: acabamos de guardar 228 bytes.
Icono del iniciador (5300 bytes, reducción del 13%) La
This link is hidden for visitors. Please Log in or register now.
0x01: recursos del sistema (predefinidos en framework-res.apk)
0x7f: recursos de la aplicación (en el archivo .apk de la aplicación)
Entonces, ¿qué sucede con nuestro APK si ponemos un enlace a un recurso en el espacio de nombres 0x01? En teoría, obtendremos un ícono más hermoso y al mismo tiempo reduciremos el tamaño de nuestro archivo.
Código:
android:icon="@android:drawable/btn_star"

Por supuesto, nunca debe confiar en los recursos del sistema como iconos en una aplicación real de trabajo. Este método fallará la validación en Google Play, y algunos fabricantes también
This link is hidden for visitors. Please Log in or register now.
El manifiesto (5252 bytes, reducción del 1%)
Todavía no hemos tocado el manifiesto.
Código:
android:allowBackup="true"
android:supportsRtl="true"
Eliminar estos atributos ahorra 48 bytes.
Hack Proguard (4984 bytes, reducción del 5%)
Parece que las clases BuildConfig y R aún permanecen en el archivo Dex.
Código:
-keep class com.fractalwrench.MainActivity { *; }
La refinación de la regla Proguard eliminará las clases innecesarias.
Ofuscación (4936 bytes, reducción del 1%)
Ofuscar el nombre de la clase Actividad. Para las clases regulares, Proguard lo hace automáticamente, pero como el nombre de la clase Activity se llama a través de Intents, no se ofuscó de manera predeterminada.
MainActivity -> c.java
com.fractalwrench.apkgolf -> cc
META-INF (3307 bytes, reducción del 33%)
En este momento, estamos firmando la aplicación con las firmas v1 y v2. Esto parece una pérdida de recursos, porque v2 proporciona
This link is hidden for visitors. Please Log in or register now.
Signature v2 no es visible desde el Analizador de APK, ya que está incluido en el bloque binario en el archivo APK. La firma v1 es visible como archivos CERT.RSA y CERT.SF.
Desactivemos la firma v1 en la interfaz de Android Studio y generemos un APK firmado. Probemos y viceversa.
Firma
Tamaño
v1
3511
v2
3307
Parece que ahora usaremos v2.
Adónde vamos: no se necesita IDE.
Es hora de editar el APK manualmente. Usamos los siguientes comandos:
Código:
# 1. Создать неподписанный apk
./gradlew assembleRelease
# 2. Разархивировать архив
unzip app-release-unsigned.apk -d app
# Сделать необходимые правки
# 3. Заархивировать архив
zip -r app app.zip
# 4. Запустить zipalign
zipalign -v -p 4 app-release-unsigned.apk app-release-aligned.apk
# 5. Запустить apksigner с подписью v2
apksigner sign --v1-signing-enabled false --ks $HOME/fake.jks --out signed-release.apk app-release-unsigned.apk
# 6. Проверить подпись
apksigner verify signed-release.apk
Una descripción detallada del proceso de firma de APK está disponible
This link is hidden for visitors. Please Log in or register now.
Un APK sin signo y sin alinear pesa 1902 bytes, lo que significa que el procedimiento agrega aproximadamente 1 kilobyte.
Tamaño de archivo no coincidente (2608 bytes, 21% de compresión)
¡Extraño! Si descomprime el APK no alineado y lo firma manualmente, el archivo META-INF / MANIFEST.MF desaparece, lo que ahorra 543 bytes. Si alguien sabe por qué sucede esto, ¡házmelo saber!
Ahora nos quedan tres archivos en el APK firmado. Pero todavía podemos deshacernos del archivo resources.arsc, ¡porque no instalamos ningún recurso!
Después de eso, solo está el archivo de manifiesto y el archivo classes.dex, ambos del mismo tamaño.
Hacks de compresión (2599 bytes, reducción en 0.5%)
Ahora cambiaremos todas las líneas restantes a 'c', actualizando las versiones a 26, y luego generaremos un APK firmado.
Código:
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "c.c"
minSdkVersion 26
targetSdkVersion 26
versionCode 26
versionName "26"
}
Código:
Code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application
android:icon="@android:drawable/btn_star"
android:label="c"
>
<activity android:name="c.c.c">
Esto reduce el tamaño en otros 9 bytes.
Aunque el número de caracteres en el archivo no ha cambiado, el hecho es que la frecuencia del carácter 'c' ha aumentado. Como resultado, el algoritmo de compresión funcionó de manera más eficiente.
Hola, ADB (2462 bytes, reducción del 5%)
Puede optimizar aún más el manifiesto eliminando el filtro de intento de lanzamiento para la clase de actividad. Desde este momento iniciaremos la aplicación con el siguiente comando:
Código:
adb shell am start -a android.intent.action.MAIN -n c.c/.c
Aquí está el nuevo manifiesto:
Código:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application>
<activity
android:name="c"
android:exported="true" />
</application>
</manifest>
También nos deshicimos del ícono del iniciador.
Eliminación de referencias a métodos (2179 bytes, reducción del 12%)
De acuerdo con las condiciones iniciales, debemos preparar un APK que pueda instalarse en el dispositivo.
Nuestra aplicación enumera los métodos en las clases TextView, Bundle y Activity. Puede reducir el tamaño del archivo Dex eliminando estos enlaces y reemplazándolos con la nueva clase de aplicación. Por lo tanto, el archivo Dex ahora se referirá a un único método: el constructor de la clase Aplicación.
Los archivos de origen ahora se ven así:
Código:
package c.c;
import android.app.Application;
public class c extends Application {}
Código:
Code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application android:name=".c" />
</manifest>
Usamos adb para verificar que el APK se haya instalado correctamente, esto también se puede verificar a través de "Configuración".

Optimización de Dex (1961 bytes, reducción del 10%)
Pasé varias horas estudiando el formato de archivo Dex para esta optimización, porque diferentes mecanismos como sumas de verificación y compensaciones dificultan la edición manual.
En resumen, resultó que el único requisito para instalar el APK es el hecho de que existe el archivo classes.dex. Por lo tanto, simplemente eliminamos el archivo original, ejecutamos touch classes.dex en la consola y ahorramos el 10% del tamaño usando un archivo vacío.
A veces la solución más tonta es la mejor.
Comprensión del manifiesto (1961 bytes, reducción del 0%)
El manifiesto APK sin firmar es un archivo XML binario que parece no estar documentado oficialmente. Puede cambiar el contenido de un archivo utilizando el editor
This link is hidden for visitors. Please Log in or register now.
Se adivinan algunos elementos interesantes en el encabezado del archivo: los primeros cuatro bytes codifican 38, que coincide con el número de versión del archivo Dex. Los siguientes dos bytes codifican 660, que coincide con el tamaño del archivo.
Intentemos eliminar un byte estableciendo targetSdkVersion en 1 y cambiando el tamaño del archivo en el encabezado a 659. Desafortunadamente, el sistema Android rechaza el nuevo archivo como un APK no válido. Parece que todo está organizado de alguna manera más complicado ...
Malentendido del manifiesto (1777 bytes, reducción del 9%)
E intente escribir caracteres aleatorios en todo el archivo y luego instale el APK sin cambiar el tamaño de archivo especificado. Esto verificará si la suma de verificación está marcada y cómo nuestros cambios afectarán las compensaciones en el encabezado del archivo.
Sorprendentemente, dicho manifiesto se percibe como un APK válido en Nexus 5X en Oreo:

Creo que acabo de escuchar al desarrollador del marco de Android responsable de apoyar BinaryXMLParser.java gritando muy fuerte en la almohada.
Para obtener el máximo beneficio, debe reemplazar todos estos caracteres tontos con bytes nulos. Esto ayudará a reconocer partes importantes del archivo en HexFiend, y también reducirá unos pocos bytes gracias al hack de compresión mencionado anteriormente. Manifiesto
UTF-8
Aquí están los componentes importantes del Manifiesto sin los cuales el APK no se instalará.

Algunas cosas son obvias, como las etiquetas de manifiesto y de paquete. En el grupo de cadenas, el código de versión y el nombre del paquete son visibles.
Manifiesto hexadecimal

Ver el archivo en hexadecimal muestra los valores en el encabezado del archivo que describen el conjunto de cadenas y otros valores, como el tamaño del archivo 0x9402. Las cadenas también están codificadas de forma interesante: si tienen más de 8 bytes, la longitud total se indica en los dos bytes anteriores.
Pero es casi imposible encontrar otras opciones de optimización aquí.
¿Ya terminaste? (1757 bytes, reducción del 1%)
Aprenderemos el APK final.

A lo largo de este nombre, el APK indicó mi nombre en la firma v2. Cree un nuevo almacén de claves que use un truco para la compresión.

Guardamos 20 bytes.
Paso 5: Reconocer
1757 bytes es muy pequeño, maldita sea. Y hasta donde yo sé, este es el APK más pequeño existente.
Sin embargo, creo razonablemente que alguien de la comunidad de Android puede realizar más optimizaciones y mejorar aún más el resultado. Si logra reducir el archivo de los 1757 bytes actuales,
This link is hidden for visitors. Please Log in or register now.
This link is hidden for visitors. Please Log in or register now.
Autor original:
This link is hidden for visitors. Please Log in or register now.
2017