Saltar al contenido principal

Soluciona la ofuscación de Google Play inferior al 25% en apps Capacitor

Supera el control de ofuscación del 25% de Google Play en una app de Capacitor Android activando R8, reduciendo DEX no usados y enviando un App Bundle de release.

Soluciona la ofuscación de Google Play inferior al 25% en apps Capacitor

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í:

Advertencia de Android vitals en Google Play Console: la ofuscación es del 3 %, por debajo del umbral de optimización del 25 %, con fecha de corrección en febrero de 2027

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:

  1. minifyEnabled true es lo que realmente ejecuta R8 (shrink + obfuscate + optimize).
  2. shrinkResources true elimina recursos de Android sin uso. Requiere minificación.
  3. Para esta configuración de R8, usa proguard-android-optimize.txt. proguard-android.txt se 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:

  • @CapacitorPlugin clases, @PluginMethod, callbacks de permisos y actividades
  • Clases que extienden com.getcapacitor.Plugin
  • Legacy @NativePlugin y 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.txt
  • app/build/outputs/mapping/release/configuration.txt
  • En el último parche de AGP 8.10 o superior, r8.json dentro 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.txt si 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:

  1. Prueba y lanza → Explorador de paquetes de apps para esa versión
  2. Tamaño DEX más porcentajes de obfuscation / optimization / shrinking
  3. 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.

  1. Abrir Analizador de configuración de R8 si tu Android Gradle Plugin es 9.3 o superior — assembleRelease luego escribe configanalyzer.html junto a mapping.txt. En AGP 9.2 y versiones anteriores, omite ese archivo HTML y usa mapping.txt, APK Analyzer y el explorador de App bundles de Play.
  2. 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.
  3. Abre la .aab en el APK Analyzer de Android Studio, selecciona el gran .dex archivos, y activa los nombres deobfuscated (requiere mapping.txt). Los paquetes que siguen siendo enormes y legibles son los que debes dejar de mantener íntegros.
  4. 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.ts no 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 (no proguard-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 .aab subido; 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.

Live updates para apps Capacitor

Cuando un bug de la capa web está en producción, publica el fix a través de Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el flujo de revisión habitual.

Lo último de nuestro blog

Capgo te da la información clave que necesitas para crear una app móvil realmente profesional.