Qué rechaza cada lector
Antes conviene leer «Contenedor ZIP» · «APK Signing Block»
1. Qué es y por qué existe
Los documentos de formatos describen cada estructura desde quien la escribe. Este la describe
desde quien la lee: qué hace el lector de la plataforma con cada cosa que no cuadra. Es la
pregunta que importa al analizar o al modificar un APK, porque un fichero que «no cumple la
especificación» puede instalarse sin un aviso, y uno que la cumple puede no instalarse.
También es donde más se equivocó este sitio. Casi todas las erratas graves corregidas estaban en
esta frontera: el CRC que libziparchive no comprueba, el bit 3 que decide el Local File Header y
no el Central Directory, o el INSTALL_PARSE_FAILED_MANIFEST_EMPTY que el instalador ya no lanza.
Todo está leído en el código de AOSP en la etiqueta android-17.0.0_r1, el 25 de septiembre de
2026. Lo que además se provocó en un emulador lleva la marca (reproducido), y su salida literal
está en la «sección 2.5 de Diagnóstico de fallos · Lo que responde adb install, reproducido».
2. Cómo leer las tablas
La columna de reacción usa tres palabras, siempre en el mismo sentido:
- Rechaza. La operación se aborta: el
APKno se abre, no se instala o la clase no se carga. - Avisa. Escribe una línea en el log del sistema y sigue como si nada.
- Ignora. Ni error ni log.
Los mensajes son literales del código, con sus %d y %s. La columna de fuente da fichero y
líneas en android-17.0.0_r1; las URL completas están en las fuentes. Y un aviso sobre cómo llega
cada rechazo al usuario: casi nunca con el mensaje de la tabla. Un fallo de libziparchive o de
LoadedArsc sale de la instalación como INSTALL_PARSE_FAILED_NOT_APK: … Failed to load asset path; uno del verificador de firmas, como INSTALL_PARSE_FAILED_NO_CERTIFICATES. El mensaje
concreto está en logcat.
3. libziparchive: el ZIP
Es el lector de ZIP de la plataforma: lo usan el instalador, AssetManager y el cargador de
DEX. Lo desarrolla «Contenedor ZIP → §11 · Lectura tolerante frente a lectura estricta».
| Condición | Reacción | Mensaje o código | Fuente |
|---|---|---|---|
La primera firma de EOCD desde el final no cuadra con el tamaño del fichero |
Rechaza | kInvalidFile; Zip: %d extraneous bytes at the end of the central directory |
zip_archive.cc:300-326 |
Ninguna firma de EOCD en los últimos 65.557 bytes |
Rechaza | kInvalidFile; EOCD not found, %s is not zip |
zip_archive.cc:310-313 |
| Menos de 22 bytes, o más de 256 GiB | Rechaza | kInvalidFile |
zip_archive.cc:372-380 |
El Central Directory se sale del espacio que le deja el EOCD |
Rechaza | kInvalidOffset; bad offsets (dir …) |
zip_archive.cc:344-348 |
| Archivo sin entradas | Rechaza | kEmptyArchive |
zip_archive.cc:412-417 |
El byte 0 no empieza por un Local File Header, como en Janus |
Rechaza | kInvalidFile; Entry at offset zero has invalid LFH signature |
zip_archive.cc:650-664 |
| Dos entradas con el mismo nombre | Rechaza el archivo entero (reproducido) | kDuplicateEntry; Found duplicate entry %s |
zip_cd_entry_map.cc:57-62 |
Nombre que no es UTF-8, con NUL o que se sale del Central Directory |
Rechaza | kInvalidEntryName |
zip_archive.cc:581-586, 617-621 |
Nombre distinto entre el Local File Header y el Central Directory |
Rechaza al buscar la entrada | kInconsistentInformation; lfh name did not match central directory |
zip_archive.cc:877-881, 910-913 |
Sin bit 3, CRC o tamaños distintos entre Local File Header y Central Directory |
Rechaza | kInconsistentInformation; size/crc32 mismatch |
zip_archive.cc:987-996 |
Bit 3 distinto entre Local File Header y Central Directory |
Avisa y usa el del Local File Header |
gpb flag mismatch at bit 3 |
zip_archive.cc:980-983 |
Con bit 3, el data descriptor no cuadra con el Central Directory al extraer |
Rechaza | size/crc32 mismatch |
zip_archive.cc:775-785 |
data descriptor sin su firma opcional 0x08074b50 |
Ignora | — | zip_archive.cc:757-758 |
| CRC-32 del contenido | Ignora: no se comprueba | kCrcChecksEnabled = false |
zip_archive.cc:72 |
Método de compresión distinto de stored (0) y deflate (8) |
Rechaza al extraer | kUnknownCompressionMethod |
zip_archive.cc:1607-1618 |
| El contenido inflado no mide lo declarado | Rechaza | size mismatch on inflated file |
zip_archive.cc:1526-1530 |
| zip64 bien formado | Lo acepta | — | zip_archive.cc:214-276 |
zip64 con uno solo de los dos tamaños del Local File Header a 0xFFFFFFFF |
Rechaza | zip64 on Android requires both compressed and uncompressed length to be UINT32_MAX |
zip_archive.cc:928-934 |
extra field distinto entre Local File Header y Central Directory, como el relleno de zipalign |
Ignora, por diseño | — | zip_archive.cc:915-923 |
extra field con un identificador desconocido |
Ignora: lo salta | — | zip_archive.cc:465-470 |
Datos antes del APK Signing Block, relleno o huecos entre entradas |
Ignora | — | Ninguna comprobación |
4. El verificador de firmas
ApkSignatureVerifier prueba v4, luego v3 —y dentro de v3, v3.2, v3.1 y v3.0—, luego v2 y por
último v1. Solo baja al esquema siguiente cuando el anterior no está; si está y falla, rechaza.
Lo desarrollan «Firma v4 y verificación → §5 · El algoritmo completo de verificación», y
«Esquemas de firma → §8 · Qué esquema exige o admite cada nivel de API».
| Condición | Reacción | Mensaje o código | Fuente |
|---|---|---|---|
Ningún esquema desde el mínimo que exige el targetSdk: v2 desde 30 |
Rechaza (reproducido) | NO_CERTIFICATES; No signature found in package of version %d or newer for package %s |
ApkSignatureVerifier.java:170-237, 579-584 |
| Un esquema presente que no verifica | Rechaza, sin probar el siguiente | NO_CERTIFICATES; Failed to collect certificates from %s using APK Signature Scheme v2 (o v3, o v4) |
ApkSignatureVerifier.java:337-343, 381-387, 410-416 |
v1: el JAR no tiene AndroidManifest.xml |
Rechaza | BAD_MANIFEST; Package %s has no manifest |
ApkSignatureVerifier.java:449-452 |
v1: AndroidManifest.xml sin certificados |
Rechaza | NO_CERTIFICATES; Package %s has no certificates at entry AndroidManifest.xml |
ApkSignatureVerifier.java:459-463 |
| v1: una entrada firmada por otros firmantes | Rechaza | INCONSISTENT_CERTIFICATES; Package %s has mismatched certificates at entry %s |
ApkSignatureVerifier.java:496-501 |
v1: el .SF dice X-Android-APK-Signed: 2 y no hay bloque v2 |
Rechaza | … but no such signature was found. Signature stripped? |
StrictJarVerifier.java:437-445 |
Un bloque con un identificador desconocido en el APK Signing Block |
Ignora | — | ApkSigningBlockUtils.java:814-822 |
| Un atributo adicional desconocido en un firmante | Ignora | — | ApkSignatureSchemeV3Verifier.java:777-779 |
| zip64 | Rechaza la firma | ZIP64 APK not supported |
ApkSigningBlockUtils.java:78-80 |
Los dos tamaños del APK Signing Block no coinciden |
Rechaza la firma | APK Signing Block sizes in header and footer do not match |
ApkSigningBlockUtils.java:775-778 |
Algo entre el Central Directory y el EOCD |
Rechaza la firma | ZIP Central Directory is not immediately followed by End of Central Directory |
ApkSigningBlockUtils.java:422-426 |
v2 anuncia v3 con 0xbeeff00d y el bloque v3 no está |
Rechaza | V2 signature indicates APK is signed using APK Signature Scheme v3, but none was found. Signature stripped? |
ApkSignatureSchemeV2Verifier.java:383-393 |
v3 anuncia v3.1 con 0x559f8b02 y el bloque v3.1 no está |
Rechaza | Expected a v3.1 signing block targeting SDK version %d, but a v3.1 block was not found |
ApkSignatureSchemeV3Verifier.java:699-720 |
v3.0 o v3.1 anuncian v3.2 con 0xbf940529 y el bloque v3.2 no está |
Rechaza en Android 17 | Expected a v3.2 signing block targeting SDK version %d to %d, but a v3.2 block was not found |
ApkSignatureSchemeV3Verifier.java:797-805 |
Copias de minSdkVersion o maxSdkVersion distintas dentro y fuera del signed data |
Rechaza | minSdkVersion mismatch between signed and unsigned in v3 signer block. |
ApkSignatureSchemeV3Verifier.java:593-612 |
| Más de un firmante en v3.0 | Rechaza | APK Signature Scheme V3 only supports one signer: multiple signers found. |
ApkSignatureSchemeV3Verifier.java:282-284 |
| Más de diez firmantes en v2 | Rechaza | APK Signature Scheme v2 only supports a maximum of 10 signers |
ApkSignatureSchemeV2Verifier.java:191-195 |
Los algoritmos de digests y de signatures no coinciden |
Rechaza | Signature algorithms don't match between digests and signatures records |
ApkSignatureSchemeV3Verifier.java:532-540 |
| La clave pública no es la del primer certificado | Rechaza | Public key mismatch between certificate and signature record |
ApkSignatureSchemeV3Verifier.java:584-591 |
| El digest del contenido no cuadra | Rechaza | %s digest of contents did not verify |
ApkSigningBlockUtils.java:185-189 |
| Un eslabón del linaje no verifica con la clave del anterior | Rechaza | Unable to verify signature of certificate #%d using %s when verifying Proof-of-rotation record |
ApkSigningBlockUtils.java:899-903 |
| El linaje no acaba en el firmante | Rechaza | Terminal certificate in Proof-of-rotation record does not match APK signing certificate |
ApkSignatureSchemeV3Verifier.java:685-687 |
v4: un .idsig legible que no corresponde al APK |
Rechaza con NO_CERTIFICATES. En una instalación incremental, antes: el sistema de ficheros no puede leer el APK y sale NOT_APK (reproducido) |
Actual digest does not match the v4 signature |
ApkSignatureSchemeV4Verifier.java:114-124 |
v4: un .idsig que no se puede abrir, o de menos de los 4 bytes de la versión |
Pasa a v3, v2 o v1 | Failed to obtain signature bytes from .idsig |
ApkSignatureSchemeV4Verifier.java:97-102 |
v4: un .idsig truncado después de la versión |
Rechaza con NO_CERTIFICATES: readBytes devuelve null y HashingInfo.fromByteArray lanza NullPointerException. Con adb install --incremental no se llega: adb falla antes en el ordenador (reproducido) |
Failed to collect certificates from %s using APK Signature Scheme v4 |
V4Signature.java:306-317, ApkSignatureVerifier.java:339-343 |
| v4: versión distinta de 2 | Rechaza | v4 signature version %d is not supported |
ApkSignatureSchemeV4Verifier.java:105-108 |
Las reglas propias del bloque v3.2 —dos firmantes, uno clásico y otro ML-DSA, mismo rango, mismo linaje— están en la «sección 7 de Esquemas de firma · v3.2: la firma híbrida».
5. El instalador
PackageInstallerSession valida la sesión, ApkLiteParseUtils y ParsingPackageUtils analizan
el manifiesto, e InstallPackageHelper decide si la actualización es compatible con lo instalado.
El catálogo de códigos, con cómo se diagnostica cada uno, es
«Diagnóstico de fallos → §2 · Instalación: los códigos INSTALL_*».
| Condición | Reacción | Código y mensaje | Fuente |
|---|---|---|---|
libziparchive o LoadedArsc no abren el APK |
Rechaza (reproducido) | INSTALL_PARSE_FAILED_NOT_APK; Failed to parse %s: Failed to load asset path %s |
ApkLiteParseUtils.java:371-373 |
No hay <manifest> |
Rechaza | ..._MANIFEST_MALFORMED; No start tag found o No <manifest> tag |
ApkLiteParseUtils.java:907-914 |
El AXML del manifiesto no parsea |
Rechaza | ..._UNEXPECTED_EXCEPTION; Corrupt XML binary file |
ApkLiteParseUtils.java:400-403 |
| Nombre de paquete inválido | Rechaza | ..._BAD_PACKAGE_NAME; Invalid manifest package: %s |
ApkLiteParseUtils.java:917-937 |
<uses-split> sin nombre, o bibliotecas SDK o estáticas mal declaradas |
Rechaza | ..._MANIFEST_MALFORMED con el mensaje concreto |
ApkLiteParseUtils.java:560-625 |
Ni <application> ni <instrumentation> |
Rechaza con targetSdk 30 o más; ignora con menos (reproducido) |
..._MANIFEST_MALFORMED; <manifest> does not contain an <application> or <instrumentation> |
ParsingPackageUtils.java:997-1005 |
resources.arsc comprimido o desalineado |
Rechaza con targetSdk 30 o más; ignora con menos (reproducido) |
-124; Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary |
ParsingPackageUtils.java:622-632 |
minSdkVersion mayor que el dispositivo |
Rechaza (reproducido) | INSTALL_FAILED_OLDER_SDK; Requires newer sdk version #%d (current version is #%d) |
FrameworkParsingPackageUtils.java:319 |
targetSdkVersion por debajo del mínimo instalable, 24 en Android 17 |
Rechaza (reproducido en Android 14, donde es 23) | INSTALL_FAILED_DEPRECATED_SDK_VERSION; App package must target at least SDK version %d, but found %d |
InstallPackageHelper.java:1691-1699 |
android:testOnly="true" sin -t |
Rechaza (reproducido) | INSTALL_FAILED_TEST_ONLY; Failed to install test-only apk. Did you forget to add -t? |
InstallPackageHelper.java:1731-1736 |
| Instalación completa sin base | Rechaza (reproducido) | INSTALL_FAILED_INVALID_APK; Full install must include a base package |
PackageInstallerSession.java:4776-4780 |
| El mismo split dos veces en la sesión | Rechaza (reproducido) | INSTALL_FAILED_INVALID_APK; Split %s was defined multiple times |
PackageInstallerSession.java:4609-4612 |
| Un split con otra firma | Rechaza (reproducido) | INSTALL_FAILED_INVALID_APK; %s signatures are inconsistent |
PackageInstallerSession.java:5154-5161 |
Un split con otro paquete u otro versionCode |
Rechaza (reproducido) | INSTALL_FAILED_INVALID_APK; %s version code %d inconsistent with %d |
PackageInstallerSession.java:5164-5180 |
isSplitRequired o requiredSplitTypes sin cubrir |
Rechaza (reproducido) | INSTALL_FAILED_MISSING_SPLIT; Missing split for %s |
PackageInstallerSession.java:4787-4791 |
android:isSplitRequired en <application> y no en <manifest> |
Ignora: el instalador solo lo lee en <manifest> (reproducido) |
— | ApkLiteParseUtils.java:445-446 |
useEmbeddedDex con algún .dex comprimido o desalineado |
Rechaza | INSTALL_FAILED_INVALID_APK; Some dex are not uncompressed and aligned correctly for %s |
PackageInstallerSession.java:4973-4981 |
Ninguna ABI compatible en lib/ |
Rechaza | INSTALL_FAILED_NO_MATCHING_ABIS |
NativeLibraryHelper.cpp:520-523 |
Una .so comprimida o desalineada con extractNativeLibs=false |
Rechaza | INSTALL_FAILED_INVALID_APK; Failed to extract native libraries, res=-2 |
NativeLibraryHelper.cpp:310-341 |
multiArch sin todas las ABIs del sistema |
Rechaza | INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS |
PackageAbiHelperImpl.java:134-146 |
| Otra firma encima de la instalada | Rechaza (reproducido) | INSTALL_FAILED_UPDATE_INCOMPATIBLE; Existing package %s signatures do not match newer version; ignoring! |
PackageManagerServiceUtils.java:528-530 |
Un versionCode menor que el instalado |
Rechaza (reproducido) | INSTALL_FAILED_VERSION_DOWNGRADE; Downgrade detected: Update version code %d is older than current %d |
PackageManagerServiceUtils.java:1372-1409 |
Otro sharedUserId en una actualización |
Rechaza | INSTALL_FAILED_UID_CHANGED |
InstallPackageHelper.java:2254-2273 |
| Un dexopt que falla al instalar | Ignora: la instalación sigue | // Don't fail application installs if the dexopt step fails. |
DexOptHelper.java:351-355 |
6. El verificador de DEX
DexFileVerifier corre la primera vez que se carga un DEX sin .vdex válido, dentro de
dex2oat y en dexdump; con un .vdex cuyos checksums cuadran, se salta. Lo desarrolla
«Formato DEX → §14 · Checksums: qué recalcular y en qué orden».
| Condición | Reacción | Mensaje | Fuente |
|---|---|---|---|
| Menos de 112 bytes | Rechaza | Empty or truncated file. |
dex_file_verifier.cc:619-621 |
magic que no empieza por dex\n |
Rechaza | Bad file magic |
dex_file_verifier.cc:623-625 |
| Versión que la plataforma no conoce | Rechaza | Unknown dex version |
dex_file_verifier.cc:627-629 |
file_size imposible |
Rechaza | Bad file size (%zu, expected at least %zu) |
dex_file_verifier.cc:636-643 |
header_size distinto de 0x70, o de 0x78 en la 041 |
Rechaza | Bad header size: %ud expected %zud |
dex_file_verifier.cc:647-650 |
endian_tag distinto de 0x12345678 |
Rechaza | Unexpected endian_tag: %x |
dex_file_verifier.cc:653-656 |
| Adler-32 que no cuadra, verificando el checksum | Rechaza | Bad checksum (%08x, expected %08x) |
dex_file_verifier.cc:660-663 |
| El mismo, sin verificar el checksum | Avisa | Ignoring bad checksum (%08x, expected %08x) |
dex_file_verifier.cc:664-667 |
La firma SHA-1 del campo signature |
Ignora: nunca se recalcula | — | dex_file.cc:78-84 |
| Un offset fuera del fichero o desalineado | Rechaza | Offset(%d) should be within file size(%zu) for %s. |
dex_file_verifier.cc:582-614 |
Más de 65.535 type_ids o proto_ids |
Rechaza | Size(%u) should not exceed limit(%u) for type-ids. |
dex_file_verifier.cc:717-722 |
map_list desordenado |
Rechaza | Out of order map item: %x then %x for type %x last type was %x |
dex_file_verifier.cc:773-780 |
Un tipo desconocido en el map_list |
Rechaza | Unknown map section type %x |
dex_file_verifier.cc:824-827 |
Un tipo repetido en el map_list |
Rechaza | Duplicate map section of type %x |
dex_file_verifier.cc:829-832 |
| MUTF-8 mal formado | Rechaza | Illegal start byte %x in string data |
dex_file_verifier.cc:1901-1953 |
| Un índice fuera de rango | Rechaza | Bad index for %s: %x >= %x |
dex_file_verifier.cc:244-250 |
La misma clase dos veces en un DEX |
Rechaza | Redefinition of class with type idx: '%u' |
dex_file_verifier.cc:1497-1500 |
Índices de miembros que retroceden en el class_data_item |
Rechaza | out-of-order static field indexes %u and %u |
dex_file_verifier.cc:278-287 |
| El mismo miembro repetido, con diferencia 0 | Avisa: ClassLinker se queda con el primero |
Duplicate fields in class %s |
class_linker.cc:4300-4388 |
string_ids desordenados |
Rechaza | Out-of-order string_ids: '%s' then '%s' |
dex_file_verifier.cc:2748-2751 |
| Una clase antes que su superclase, desde la 037 | Rechaza | Invalid class definition ordering: … |
dex_file_verifier.cc:3019-3033 |
| Relleno distinto de cero entre secciones, hasta la 040 | Rechaza | Non-zero padding %x before section of type %zu at offset 0x%zx |
dex_file_verifier.cc:1046-1053 |
Flags de acceso incoherentes en un DEX 035 |
Avisa; desde la 037, rechaza | This dex file is invalid and will be rejected in the future. Error is: … |
dex_file_verifier.cc:3661-3678 |
Un espacio en un nombre simple, en un DEX 035 |
Lo acepta: el verificador no mira la versión | — | descriptors_names.cc |
La misma clase en dos classes*.dex |
Ignora: gana la del primero | — | class_linker.cc:3242-3250 |
classes.dex comprimido o desalineado dentro del APK |
Avisa y lo extrae a memoria | Can't mmap dex file %s directly; please zipalign to use it from the APK |
dex_file_loader.cc:549-564 |
Una entrada classes*.dex vacía |
Rechaza | Dex file '%s' has zero length |
dex_file_loader.cc:539-543 |
Más de 100 DEX en un contenedor 041 |
Avisa | … has in excess of 100 dex files. Please consider coalescing … |
dex_file_loader.cc:429-433 |
Qué versión del magic acepta cada plataforma, leído en las etiquetas: 035 desde siempre, 037
desde android-7.0.0_r1, 038 desde la 8.0, 039 desde la 9, 040 desde android-11.0.0_r1 —no
desde la 10, pese a lo que dicen la especificación y el comentario del código— y 041 desde la 15.
7. ClassLinker y el verificador de bytecode
El verificador de bytecode distingue dos clases de fallo, y la diferencia decide cuándo muere la aplicación. Los mensajes de las comprobaciones estáticas están en «Bytecode Dalvik → §10 · La verificación de bytecode de ART».
| Condición | Reacción | Mensaje | Fuente |
|---|---|---|---|
| Fallo duro: registro fuera de rango, destino de salto inválido, tipos incompatibles | Rechaza la clase la primera vez que se usa, no al instalar | java.lang.VerifyError; Verifier rejected class %s: %s |
class_linker.cc:5400-5406, method_verifier.cc:2753-2754 |
| Fallo blando: método, campo o clase que no se resuelven, acceso | No rechaza la clase: la excepción salta al ejecutar esa instrucción | NoSuchMethodError, NoSuchFieldError, IllegalAccessError… |
method_verifier.cc:6050-6068 |
Un fallo duro con targetSdk por debajo de 32, en código que el verificador da por inalcanzable |
Se degrada a excepción en ejecución | — | method_verifier.cc:5684-5695 |
| Volver a inicializar una clase que ya falló | Rechaza | Rejecting re-init on previously-failed class %s |
class_linker.cc:542-586 |
8. ResXMLTree: el XML binario
El analizador de AXML de libandroidfw, que lee el manifiesto y los layouts. En la
instalación, cualquier rechazo suyo llega como INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION con
Corrupt XML binary file. Lo desarrolla «XML binario → §7 · Manifiestos malformados: ofuscación y evasión de análisis».
| Condición | Reacción | Mensaje | Fuente |
|---|---|---|---|
headerSize más pequeño que el mínimo, o mayor que size |
Rechaza | %s header size 0x%04x is too small. |
ResourceTypes.cpp:140-145 |
size o headerSize que no son múltiplo de 4 |
Rechaza | %s size 0x%x or headerSize 0x%x is not on an integer boundary. |
ResourceTypes.cpp:136-138 |
| Un chunk que se sale del fichero | Rechaza | %s data size 0x%x extends beyond resource end %p. |
ResourceTypes.cpp:132-134 |
El chunk raíz no es de tipo 0x0003, desde android-14.0.0_r29 |
Rechaza | Bad XML block: expected root block type %d, got %d |
ResourceTypes.cpp:1919-1924 |
| Un chunk desconocido en el nivel superior | Ignora | — | ResourceTypes.cpp:1971-1975 |
| Ningún nodo raíz | Rechaza | Bad XML block: no root element node found |
ResourceTypes.cpp:1981-1985 |
| Ningún string pool antes del primer nodo | Rechaza | NO_INIT |
ResourceTypes.cpp:1987 |
| El string pool declara más cadenas de las que caben | Rechaza | Bad string block: entry of %d items extends past data size %d |
ResourceTypes.cpp:568-576 |
| La última cadena sin terminar | Rechaza | Bad string block: last string is not 0-terminated |
ResourceTypes.cpp:634-646 |
Los estilos no acaban en 0xFFFFFFFF |
Rechaza | Bad string block: last style is not 0xFFFFFFFF-terminated |
ResourceTypes.cpp:701-710 |
| Una cadena concreta sin terminar | Avisa y la devuelve vacía; el resto sigue | Bad string block: string #%d is not null-terminated |
ResourceTypes.cpp:839-842 |
| Un tipo de nodo desconocido | Avisa y lo salta | Unknown XML block: header type %d … |
ResourceTypes.cpp:1780-1784 |
attributeSize menor que 0x14 |
Rechaza | Bad XML block: attribute size %d is smaller than min expected %d |
ResourceTypes.cpp:2036-2040 |
| Atributos que se salen del nodo | Rechaza | Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes |
ResourceTypes.cpp:2041-2049 |
Espacios de nombres sin cerrar, o un END_ELEMENT de más |
Ignora | — | Ninguna comprobación |
9. LoadedArsc y AttributeResolution: los recursos
LoadedArsc carga resources.arsc; cualquier rechazo suyo deja el APK sin abrir, y en la
instalación llega como INSTALL_PARSE_FAILED_NOT_APK. Lo desarrolla
«Tabla de recursos → §10 · ResTable_entry, ResTable_map_entry y ResTable_map».
| Condición | Reacción | Mensaje | Fuente |
|---|---|---|---|
| Un chunk con cabecera demasiado pequeña, o más grande que los datos | Rechaza | header size too small / chunk size is bigger than given data |
LoadedArsc.cpp:68-107 |
| Un chunk de tipo desconocido | Avisa y lo salta | Unknown chunk type '%02x'. |
LoadedArsc.cpp:875-877 |
Un ResTable_type con id 0 |
Rechaza | RES_TABLE_TYPE_TYPE has invalid ID 0. |
LoadedArsc.cpp:93-96 |
| Más de 65.535 entradas en un tipo | Rechaza | RES_TABLE_TYPE_TYPE has too many entries (%zu). |
LoadedArsc.cpp:98-102 |
| Offsets de entradas que pisan los datos | Rechaza | RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data. |
LoadedArsc.cpp:111-114 |
| Entradas que empiezan desalineadas | Rechaza | RES_TABLE_TYPE_TYPE entries start at unaligned address. |
LoadedArsc.cpp:121-124 |
Un ResTable_type sin su ResTable_typeSpec delante |
Rechaza | RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE. |
LoadedArsc.cpp:484-493 |
Dos ResTable_typeSpec con el mismo id |
Avisa | RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x |
LoadedArsc.cpp:658-661 |
| Un paquete con cabecera de menos de 284 bytes | Rechaza | RES_TABLE_PACKAGE_TYPE too small. |
LoadedArsc.cpp:530-536 |
| Más paquetes de los que declara la cabecera | Rechaza | More package chunks were found than the %zu declared in the header. |
LoadedArsc.cpp:990-994 |
| Una entrada que no cabe o está desalineada | Rechaza | Entry at offset %u is not 4-byte aligned. |
LoadedArsc.cpp:128-219 |
| Entradas dispersas desordenadas | Ignora: la búsqueda binaria encuentra otra o ninguna | — | LoadedArsc.cpp:276-283 |
Un atributo fuera de orden en un AXML |
Ignora: no se encuentra y vale TYPE_NULL |
— | AttributeResolution.cpp:352-384 |
10. Lo que pasa en silencio
Juntando la columna de «Ignora» de todas las tablas sale la lista de lo que un analizador no
puede dar por comprobado solo porque el APK se instala:
- El CRC-32 de las entradas del ZIP, y cualquier diferencia de
extra fieldentre las dos cabeceras. - Lo que haya entre los datos y el
Central Directory: elAPK Signing Blocky cualquier otra cosa que alguien ponga ahí. - Los bloques y atributos de firma que el verificador no conoce.
- La firma SHA-1 de la cabecera del
DEX. - La segunda copia de una clase repetida en otro
classes*.dex. - Los chunks desconocidos del
AXMLy los atributos desordenados. - Las entradas dispersas desordenadas de
resources.arsc. - Con
targetSdkpor debajo de 30, unresources.arsccomprimido o un manifiesto sin<application>.
Fuentes
Todas las líneas citadas son de la etiqueta android-17.0.0_r1, consultada el 25 de septiembre
de 2026 con ?format=TEXT.
system/libziparchive— https://android.googlesource.com/platform/system/libziparchive/+/refs/tags/android-17.0.0_r1/zip_archive.cc y, en el mismo directorio,zip_cd_entry_map.cc. De aquí sale la «sección 3 · libziparchive: el ZIP».- Verificación de firmas en
frameworks/base— https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/java/android/util/apk/ (ApkSignatureVerifier.java,ApkSignatureSchemeV2Verifier.java,ApkSignatureSchemeV3Verifier.java,ApkSignatureSchemeV4Verifier.javayApkSigningBlockUtils.java) y https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/java/android/util/jar/StrictJarVerifier.java. De aquí sale la «sección 4 · El verificador de firmas». - El instalador —
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/services/core/java/com/android/server/pm/
(
PackageInstallerSession.java,InstallPackageHelper.java,PackageManagerServiceUtils.java,PackageAbiHelperImpl.javayDexOptHelper.java), https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/java/android/content/pm/parsing/ApkLiteParseUtils.java, https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java y https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/jni/com_android_internal_content_NativeLibraryHelper.cpp. De aquí sale la «sección 5 · El instalador». - ART —
https://android.googlesource.com/platform/art/+/refs/tags/android-17.0.0_r1/libdexfile/dex/
(
dex_file_verifier.cc,dex_file_loader.cc,dex_file.ccydescriptors_names.cc), https://android.googlesource.com/platform/art/+/refs/tags/android-17.0.0_r1/runtime/class_linker.cc y https://android.googlesource.com/platform/art/+/refs/tags/android-17.0.0_r1/runtime/verifier/method_verifier.cc. De aquí salen las secciones «6» y «7». Las versiones demagicpor plataforma salen destandard_dex_file.ccen las etiquetasandroid-7.0.0_r1,android-8.0.0_r1,android-9.0.0_r1,android-10.0.0_r1,android-11.0.0_r1yandroid-15.0.0_r1. libandroidfw— https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/libs/androidfw/ (ResourceTypes.cpp,LoadedArsc.cppyAttributeResolution.cpp). De aquí salen las secciones «8» y «9».- Emulador Android 14
arm64-v8a— ejecutado el 25 de septiembre de 2026 conAPKde prueba construidos conaapt2y firmados conapksigner. De aquí salen las filas marcadas (reproducido); la salida literal está en la «sección 2.5 de Diagnóstico de fallos · Lo que responde adb install, reproducido».