Play Console ahora está marcando apps de Capacitor Android por App optimization is below our threshold, a menudo con Ofuscación ha persistido 3%. Google exige al menos 25% ofuscación, optimización y reducción de tamaño. La obligatoriedad empieza en febrero de 2027, y no cumplirlo puede reducir la visibilidad y las opciones de publicación.
La advertencia en Android vitals se ve así:

Este es un problema de DEX nativo de Android. No tiene que ver con tu bundle de Vue, React o Angular. Capgo los Live Update tampoco cambian esta puntuación. Se soluciona en el release build de Android Gradle y luego se sube un nuevo App Bundle.
Qué está midiendo Google
Google Play inspecciona el DEX en tu Android App Bundle: Java y Kotlin compilados, incluyendo Capacitor, plugins y AndroidX. Desde febrero de 2027, las apps con más de 10 MB de DEX deben cumplir 25% en estos tres puntos:
| Métrica | Qué significa | Causa típica de Capacitor para un score bajo |
|---|---|---|
| Obfuscation | Nombres de clases, campos y métodos renombrados a nombres cortos | minifyEnabled sigue siendo false |
| Optimización | R8 hace inline, fusiona y reescribe el bytecode | Predeterminado proguard-android.txt incluye -dontoptimize |
| Reducción | Se eliminan clases y métodos sin uso | El shrinking de Resource/code nunca se activó |
Play lee r8.json cuando haces el build con el último parche de Android Gradle Plugin 8.10 o superior. De lo contrario, usa mapping.txt, y luego heurísticas de DEX. Una app Capacitor publicada sin minificación apenas tiene archivo de mapping, así que Play ve nombres legibles y reporta unos pocos por ciento de ofuscación (a menudo restos de AARs de librerías ya ofuscadas). Eso coincide con un 3% score de vitals.
Política oficial: Requisitos de calidad técnica de Play Console. Detalle de implementación: Optimización de DEX code y habilitar la optimización de la app con R8.
Por qué las apps Capacitor fallan este check
La plantilla de Android de Capacitor sigue enviando release builds sin R8:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Ese es el valor por defecto en android-template/app/build.gradle. Las builds de debug deben quedarse así. Las de release no, si vas a publicar en Play.
Tu JavaScript ya está minificado por Vite o webpack. Play no cuenta eso. Solo cuentan los nombres DEX nativos, los code nativos sin usar y las optimizaciones de R8.
Paso 1 — Activa R8 para release
Abrir android/app/build.gradle (Groovy es el Capacitor por defecto) y cambia el lanzamiento bloque:
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
Si el módulo usa Kotlin DSL (build.gradle.kts):
buildTypes {
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
Tres detalles clave:
minifyEnabled truees lo que realmente ejecuta R8 (shrink + obfuscate + optimize).shrinkResources trueelimina recursos de Android sin uso. Requiere minificación.- Para esta configuración de R8, usa
proguard-android-optimize.txt.proguard-android.txtse lanzan-dontoptimize, lo que bloquea las optimizaciones de R8 y falla en AGP 9. Play permite cualquier shrinker; las apps de Capacitor deberían usar R8 con los valores de optimize por defecto. Ver Error de build de Capacitor Plugin con AGP 9: solución si un plugin sigue haciendo referencia al archivo antiguo.
No configures minifyEnabled true en debug. El modo Release-only mantiene las ejecuciones locales rápidas y los stack traces legibles.
Paso 2 — No desactives el modo completo de R8
Abrir android/gradle.properties y elimina esta línea si existe:
android.enableR8.fullMode=false
AGP 8+ ya habilita el modo completo. Dejar esa flag activa limita la optimización.
También busca android/app/proguard-rules.pro (y cualquier archivo -include extra) para:
-dontobfuscate
-dontoptimize
-dontshrink
-keep class ** { *; }
Esas reglas mantendrán los puntajes de Play bajos incluso después de minifyEnabled. Elimínalas a menos que tengas una razón temporal documentada.
Paso 3 — Mantén los plugins Capacitor, no toda la app
R8 usa metadatos de reflexión. Los plugins de Capacitor se detectan mediante anotaciones, por lo que necesitan keep rules. Normalmente no las añades tú mismo. Desde Capacitor 3.2.3, @capacitor/android incluye reglas de ProGuard para consumer que mantienen:
@CapacitorPluginclases,@PluginMethod, callbacks de permisos y actividades- Clases que extienden
com.getcapacitor.Plugin - Legacy
@NativePluginy clases de plugins de Cordova
Mantente en una línea actual de Capacitor 6/7/8 para que se apliquen esas reglas de consumo.
Añade reglas extra en android/app/proguard-rules.pro solo para un crash que puedas reproducir en un release build. Lo específico vence a lo general:
# Good: one misbehaving plugin package
-keep class com.mycompany.myplugin.** { *; }
# Bad: this will tank obfuscation and shrinking
-keep class com.getcapacitor.** { *; }
-keep class ** { *; }
Si un plugin de terceros sigue dando crash tras una regla de keep específica, actualiza el plugin o considera una alternativa mantenida de directorio del plugin Capgo, o pregunta Consultoría de Capgo para parchearlo.
Notas oficiales de Capacitor: Uso de ProGuard.
Paso 4 — Generar un bundle de release real
Los APK de debug seguirán mostrando ~0% de obfuscación. Play solo califica lo que subes.
Desde la raíz del proyecto:
npm run build
npx cap sync android
cd android
./gradlew bundleRelease
Sin un release signingConfig, estas tareas se completarán igualmente pero generarán un .aabsin firmar. Fírmalo en Android Studio antes de subirlo a Play.
Instala un APK de release en un dispositivo (./gradlew assembleRelease, luego el APK en app/build/outputs/apk/release/). Un .aab es un formato de subida a Play, no algo para sideload. Prueba los plugins nativos (camera, push, file, billing, auth). Los bugs de R8 no aparecen en npx cap run android sesiones de debug.
Tras los comandos de Gradle anteriores (estás en android/), confirma que R8 se ejecutó:
app/build/outputs/mapping/release/mapping.txtapp/build/outputs/mapping/release/configuration.txt- En el último parche de AGP 8.10 o superior,
r8.jsondentro del App Bundle
Esos release carpetas son la variante Capacitor por defecto. Con product flavors, el mapping está bajo el nombre de la variante (mapping/freeRelease/). El APK está en apk/<flavor>/release/ (por ejemplo apk/free/release/).
Si mapping.txt falta, estás en la carpeta de la variante incorrecta, CI ensambló debug, o R8 se ejecutó con -dontobfuscate. Revisa minifyEnabled true en release y que las reglas keep no desactiven la ofuscación.
Paso 5 — Mantén legibles los crash reports
Los stack traces ofuscados no sirven sin el archivo mapping. Busca mapping.txt para cada versión de Play:
- Play Console: Pruebas y lanzamientos → Explorador de paquetes de apps → Descargas → Recursos, luego haz upload
mapping.txtsi aún no está adjunto. - Firebase Crashlytics / Sentry: sube el mismo mapping como parte del CI.
Android Studio / AGP suele incrustar el mapping en el .aab. Aun así, verifica la pestaña Assets tras la primera subida optimizada.
Paso 6 — Sube y vuelve a revisar Play
Sube el nuevo .aab a una vía de pruebas internas (no hace falta producción para refrescar el score). Abre:
- Prueba y lanza → Explorador de paquetes de apps para esa versión
- Tamaño DEX más porcentajes de obfuscation / optimization / shrinking
- Monitorizar y mejorar → Android vitals después de que Play analice la nueva versión
Necesitas 25% en cada una de las tres métricas, no solo la ofuscación. Activar R8 con proguard-android-optimize.txt suele elevar una app Capacitor de una ofuscación de un solo dígito a más del 25% en las tres.
Solo en Play impone el mínimo del 25% cuando el DEX supera los 10 MB (50 MB en juegos). Incluso por debajo, vale la pena: DEX más pequeño, menos memoria y arranque más rápido.
Si todavía estás por debajo del 25%
R8 está activo, pero Play (o el analizador local) muestra un score bajo. El culpable suelen ser las reglas 'keep' demasiado amplias.
- Abrir Analizador de configuración de R8 si tu Android Gradle Plugin es 9.3 o superior —
assembleReleaseluego escribeconfiganalyzer.htmljunto amapping.txt. En AGP 9.2 y versiones anteriores, omite ese archivo HTML y usamapping.txt, APK Analyzer y el explorador de App bundles de Play. - Ordena las reglas keep según cuánto congelen la app. Es normal no poder editar reglas de librerías. A nivel de app
-keep class com.foo.** { *; }no lo es. - Abre la
.aaben el APK Analyzer de Android Studio, selecciona el gran.dexarchivos, y activa los nombres deobfuscated (requieremapping.txt). Los paquetes que siguen siendo enormes y legibles son los que debes dejar de mantener íntegros. - Actualiza los plugins que aún referencian
proguard-android.txt. Ese archivo bloquea la optimización en AGP 9 y es una señal de alerta en plugins antiguos.
No intentes “arreglar” una puntuación baja reduciendo el DEX con minifyEnabled false y esperando que cambien las heurísticas. Play busca reducción, optimización, y y ofuscación.
Lo que esto no reemplaza
- La minificación de JavaScript en
vite.config.tsno mueve esta métrica. - actualizaciones Live Update de Capgo envían HTML/JS/CSS. No reconstruyen el DEX. Una vez que R8 está activado en el binario de la tienda, puedes seguir enviando fixes de JS vía OTA. La comprobación de ofuscación en sí requiere una subida nativa a Play.
- Tamaño de página de 16 KB es un requisito nativo de Play independiente. Ver Tamaño de página de 16 KB en Android.
Si ya haces el build de Android con Build de Capgo, cambia android/app/build.gradle en el repo. El siguiente cloud build usará R8. No necesitas un pipeline de Play distinto, solo un binario de release con minificación activada. Lo mismo ocurre si usas GitHub Actions para builds de Android: el workflow debe hacer el assemble release, no debug.
FAQ
¿Activar R8 romperá mis plugins Capacitor?
Puede pasar si un plugin usa reflection y no incluye reglas de keep para el consumidor. El Capacitor core ya mantiene las clases de los plugins. Prueba un build de release. Añade un reducir aplica la regla solo al paquete que falla. Si el plugin no tiene soporte, Consultoría de Capgo puedes hacer un fork y seguir compilándolo.
¿Esto npx cap run demuestra que pasé el check?
No. Ese comando usa un build de debug con R8 desactivado. Usa bundleRelease / un upload firmado para Play.
Ya configuramos minifyEnabled true y seguimos viendo un 3%. ¿Por qué?
Busca -dontobfuscate, proguard-android.txt, android.enableR8.fullMode=false, y una regla -keep reglas. Confirma que el CI subió el AAB minificado y no un artefacto antiguo.
¿Necesitamos ProGuard en lugar de R8?
No. R8 es el shrinker del Android Gradle Plugin. Lee archivos de reglas estilo ProGuard. La doc de Google Play permite cualquier shrinker; R8 es el que las apps de Capacitor deben usar.
Checklist
-
release { minifyEnabled true; shrinkResources true } -
proguard-android-optimize.txt(noproguard-android.txt) - No
-dontobfuscate/-dontoptimize/ a nivel de app-keep class ** - Capacitor 3.2.3+ para aplicar reglas del consumidor del plugin
- El build de release genera
mapping.txt - Plugins nativos probados en una instalación de release
- Nuevo
.aabsubido; mapping adjunto en el App bundle explorer - Ofuscación, optimización y reducción: +25% en cada una
Ese es el aviso completo de Play Console: Capacitor dejó R8 desactivado, Play empezó a medir el DEX, y la solución es un cambio de una línea en el Gradle de release y un upload a la tienda.
Continúa con Fix Google Play Obfuscation Below 25% in Capacitor Apps
Si estás usando Soluciona la ofuscación de Google Play inferior al 25% en apps Capacitor para planificar lanzamientos en la tienda de Android, conéctalo con Native Builds de Capgo para App Bundles de release, CI/CD de Capgo para el pipeline de upload, Integración CI/CD para detalles de implementación, Build automático de Android de Capacitor con acciones de GitHub para pipelines self-hosted, y Consultoría de Capgo si un plugin falla tras activar R8.