GOOGLE PLAY E PUBLICAÇÃO

Como corrigimos a baixa otimização DEX no Google Play

Relato de um caso real no app SimpleTaskFlow (React Native, Expo SDK 57, build Android via EAS Build): alerta de baixa otimização DEX, investigação assistida por IA e correções que contribuíram para a melhora das métricas no Play Console — sem confundir ofuscação e tamanho de download.

1. Contexto e problema

O SimpleTaskFlow é um aplicativo Android da PHR Software, desenvolvido com React Native e Expo, publicado no Google Play em ciclo de testes fechados. Na versão 1.2.0, o Play Console passou a sinalizar baixa otimização DEX e uma taxa de ofuscação muito baixa (1%), junto a um download estimado de cerca de 26,7 MB.

Resultado observado (Play Console — SimpleTaskFlow) Versão 1.2.0: ofuscação 1%, otimização DEX baixa, DEX descompactado 46,5 MB (Figura 1). Download estimado ~26,7 MB: valor histórico observado no Google Play Console, sem figura de entrega correspondente neste artigo.

O objetivo não era apenas “diminuir MB”, e sim atender às recomendações de qualidade do Android, reduzir superfície desnecessária (permissões, bytecode) e publicar builds de release mais adequados — com revisão humana em cada passo.

2. O alerta apresentado pelo Google Play

No painel de qualidade do app, o Google Play destaca otimização do bytecode DEX, ofuscação e tamanho de entrega. Com ofuscação próxima de 1%, o console classifica a otimização como insuficiente e sugere revisar a minificação e a ofuscação com R8, respeitando as regras de preservação de código aplicáveis, além de dependências que impedem redução efetiva.

Google Play Console — SimpleTaskFlow 1.2.0: otimização de código DEX baixa, ofuscação 1%, tamanho total do DEX descompactado 46,5 MB; configuração R8 não informada.

Abrir captura em tamanho maior

Figura 1 — painel de otimização DEX no Google Play Console: SimpleTaskFlow 1.2.0 (otimização baixa, ofuscação 1%, DEX descompactado 46,5 MB). Evidência PHR, out/2026.

3. DEX, R8, ofuscação e redução de código

DEX (Dalvik Executable) é o formato de bytecode que o Android executa para código Java/Kotlin e bibliotecas compatíveis compiladas nesse pipeline. Em apps React Native/Expo, o bundle JavaScript (Hermes ou equivalente) é um artefato distinto do DEX: o Play Console avalia sobretudo o bytecode DEX gerado no build Android (Gradle), não o JS empacotado separadamente.

R8 é a ferramenta padrão do Android que faz shrink (remove código não usado), obfuscation (ofusca) e otimizações. Em builds release, habilitar a minificação e a ofuscação com R8, respeitando as regras de preservação de código aplicáveis, costuma aumentar a porcentagem de ofuscação reportada pelo Play Console — métrica distinta do tamanho de download.

Distinção importante A porcentagem de ofuscação (ex.: 1% → 92%) mede quanto do código elegível foi ofuscado segundo o relatório do Play. A redução de MB (ex.: 26,7 → 16,7) é outra métrica (download estimado). Correlacionam-se, mas não são a mesma coisa.

4. Investigação e identificação da causa

A investigação combinou leitura do relatório no Play Console, análise do manifesto Android gerado pelo projeto Expo, comparação (diff) entre builds e apoio de IA no Cursor para mapear permissões e flags de release — sempre validando sugestões no repositório e na documentação oficial.

Hipóteses investigadas

Confirmadas por configuração, manifesto ou métricas do Play (comparando releases 1.2.0 e 1.3.0):

  • Release 1.2.0 sem minificação R8 efetiva no variant publicado; na 1.3.0, enableMinifyInReleaseBuilds: true via expo-build-properties.
  • SYSTEM_ALERT_WINDOW declarada no manifesto embarcado da 1.2.0 e ausente na 1.3.0 após blockedPermissions, coerente com o uso real do app.

Não verificadas de forma conclusiva neste relato (inferência ou efeito indireto):

  • Quanto cada dependência nativa limita, isoladamente, a redução de bytecode (comum em apps React Native).
  • Se outras permissões herdadas além de SYSTEM_ALERT_WINDOW influenciaram métricas do Play — não foram objeto de captura dedicada aqui.
Configuração aplicada (caso PHR — v1.3.0) Na versão 1.3.0: R8 habilitado em release via expo-build-properties (enableMinifyInReleaseBuilds: true) e SYSTEM_ALERT_WINDOW bloqueada no Expo (blockedPermissions), coerente com o manifesto do release publicado. O pacote enviado à Play foi produzido com perfil de build production (EAS Build), alinhado à faixa 1.3.0. A evidência pública neste artigo limita-se à configuração descrita, às métricas do Play Console documentadas nas figuras e à documentação oficial.
Recomendação Em outros projetos Expo/RN, caminhos Gradle e plugins podem diferir. Confirme sempre com a documentação pública do EAS Build e da sua versão do SDK — não assuma que este caso se replica automaticamente em todas as versões do Expo.

5. Prompts técnicos para a auditoria

Quatro prompts revisados pela PHR, reutilizáveis em outros projetos Expo/React Native. Eles não são transcrições de chat: foram consolidados a partir do caso SimpleTaskFlow, com dados sensíveis removidos. Copie o bloco inteiro para o Cursor ou outra IA e adapte versões, pacotes e caminhos ao seu repositório.

Prompt 1 — Diagnóstico do alerta DEX

Objetivo: Interpretar o alerta de baixa otimização DEX no Google Play Console e produzir um diagnóstico priorizado (configuração de release, R8/minificação, plugins Expo, perfil EAS), sem alterar código.

Versão revisada e reutilizável — inspirada no caso SimpleTaskFlow (Expo SDK 57, EAS Build). Resultados no Play Console variam por app, SDK e artefato publicado; não presuma os mesmos percentuais de ofuscação ou MB.

Pré-requisitos:

  • Repositório Expo/React Native aberto no editor; branch de trabalho definida.
  • Valores que você viu no Play Console (ofuscação, DEX, download estimado) anotados — a IA deve usar só o que você informar.
  • Identificação de qual versão (versionName / faixa) está publicada ou em teste.
Prompt 1 — texto completo
Contexto: aplicativo React Native com Expo (managed ou prebuild), builds Android via EAS. O Google Play Console exibe alerta ou classificação baixa de otimização DEX / ofuscação na versão que está na loja ou em teste fechado.

Modo: INVESTIGAÇÃO SOMENTE LEITURA. Não editar arquivos, não instalar pacotes, não executar eas build, não commitar, não publicar.

Tarefas:
1. Explicar em linguagem clara o que o Play Console costuma medir neste contexto: bytecode DEX, percentual de ofuscação reportado, download estimado por aparelho — e por que essas métricas não são intercambiáveis.
2. Listar arquivos e configs que devo inspecionar neste projeto Expo, na ordem mais útil: package.json (expo, react-native, plugins), app.json ou app.config, eas.json (perfis de build), pasta android/ se existir (build.gradle release, proguard/r8), artefatos locais AAB/APK se eu indicar que tenho cópias.
3. Verificar se há expo-build-properties (ou equivalente) e se enableMinifyInReleaseBuilds (ou flags Gradle minifyEnabled / shrinkResources no variant release) estão declarados para o build que alimenta a Play Store — distinguir configuração declarada de efeito no artefato.
4. Identificar qual perfil EAS (production, preview, etc.) provavelmente gera o pacote da loja versus builds internos de teste (APK). Se não houver evidência no repositório, declarar lacuna e pedir confirmação minha — sem solicitar URLs de dashboard, IDs de build ou credenciais.
5. Produzir diagnóstico em três blocos: FATOS (métricas e versões que eu informei + trechos de config encontrados), HIPÓTESES (release sem minify, permissões herdadas, profile errado), RECOMENDAÇÕES ordenadas por impacto e risco.
6. Não inventar números de ofuscação ou MB; não prometer que habilitar a minificação e a ofuscação com R8, respeitando as regras de preservação de código aplicáveis, resolve sozinho sem testes funcionais.

Entrega: checklist numerado para eu validar antes de qualquer implementação.

Adaptar ao seu projeto: substitua a versão do SDK Expo, o nome do app e os valores do Play Console; inclua o caminho raiz do repositório apenas no chat local (não publique caminhos pessoais em artigos ou issues públicas).

Prompt 2 — Auditoria de permissões e configuração

Objetivo: Auditar permissões Android e configuração de release (expo-build-properties, EAS), identificar excessos com evidência e propor correção mínima — sem remover permissões sem análise de uso.

Versão revisada e reutilizável — no caso SimpleTaskFlow, a permissão SYSTEM_ALERT_WINDOW foi bloqueada via blockedPermissions no app.json após confirmar que o app não usa overlay flutuante; minificação release usou expo-build-properties com enableMinifyInReleaseBuilds: true (SDK 57). Outros apps podem precisar de outras permissões ou regras ProGuard.

Pré-requisitos:

  • Lista de funcionalidades reais do app (notificações, alarmes exatos, armazenamento, etc.).
  • Manifesto mergeado ou saída de npx expo prebuild --no-install (somente leitura) se android/ não estiver versionado.
  • Diagnóstico do Prompt 1 ou equivalente.
Prompt 2 — texto completo
Contexto: pós-diagnóstico de otimização DEX no Google Play. Suspeita de permissões declaradas sem uso no app e/ou release Android sem minificação R8 efetiva no variant publicado.

Modo: AUDITORIA. Pode sugerir edits, mas NÃO aplicar alterações até eu aprovar explicitamente.

Tarefas — permissões:
1. Mapear todas as permissões no AndroidManifest efetivo (app + bibliotecas). Para cada permissão sensível ou incomum, indicar provável origem (app.json permissions/blockedPermissions, plugin Expo, dependência nativa).
2. Cruzar com as funcionalidades que descrevo abaixo. Marcar como REMOVÍVEL/BLOQUEÁVEL somente com justificativa; se houver dúvida, manter e explicar o risco de remover.
3. Para apps sem overlay flutuante, explicar quando faz sentido usar android.blockedPermissions com SYSTEM_ALERT_WINDOW no Expo — e quando NÃO fazer (biblioteca que exige overlay, debug tools, etc.).

Tarefas — release / R8:
4. Inspecionar expo-build-properties (versão no package.json) e plugins em app.json/app.config. Confirmar se enableMinifyInReleaseBuilds está true para release. Verificar se enableShrinkResourcesInReleaseBuilds existe; se ausente, dizer o que isso implica (não assumir que está ativo).
5. Revisar eas.json: perfis preview vs production, buildType (apk vs app-bundle), autoIncrement, appVersionSource remote/local. Avaliar se o build que vai à loja usa o mesmo variant otimizado que testamos internamente.
6. Listar riscos de compatibilidade: notificações locais, alarmes exatos (SCHEDULE_EXACT_ALARM), reflexão/React Native, bibliotecas que quebram com minify — citar necessidade de regras ProGuard keep quando aplicável.

Entrega:
- Tabela: permissão | origem | usada? | ação recomendada (manter / blockedPermissions / investigar lib).
- Diff mínimo proposto (app.json, package.json se faltar dependência, eas.json se precisar perfil de teste).
- Não recomendar bump de Expo SDK ou AGP sem justificar impacto e escopo de reteste.

Adaptar: descreva suas funcionalidades reais no chat; ajuste nomes de permissões além de SYSTEM_ALERT_WINDOW se o manifesto listar outras herdadas.

Prompt 3 — Implementação controlada da solução

Objetivo: Implementar minificação no release Android compatível com o Expo SDK instalado, bloquear apenas permissões comprovadamente desnecessárias e, se fizer sentido, criar perfil EAS de testes internos otimizado — sempre com aprovação antes de builds ou publicação.

Versão revisada e reutilizável — padrão validado no caso PHR: dependência expo-build-properties alinhada ao SDK (ex.: ~57.0.x no SDK 57), plugin com enableMinifyInReleaseBuilds: true, blockedPermissions para permissões confirmadas como desnecessárias, perfil preview-optimized (APK interno) para testar antes do AAB production. Não garante métricas específicas no Play Console.

Pré-requisitos:

  • Auditoria do Prompt 2 aprovada por mim.
  • Cópia de segurança ou branch dedicada; alterações locais identificadas e revisadas.
  • Decisão explícita sobre incremento de versionName/versionCode.
Prompt 3 — texto completo
Contexto: auditoria concluída; vou autorizar implementação mínima para melhorar otimização DEX/R8 no release Android (Expo + EAS).

Regras de governança (obrigatórias):
- Antes de editar: mostrar plano e diff esperado; aguardar minha aprovação.
- Antes de eas build, push, submit ou upload Play: pedir aprovação separada.
- PROIBIDO: git push --force, alterar versionCode/versionName sem minha confirmação, remover permissões ainda necessárias, bump de Expo/RN sem plano de reteste.
- Minificação NÃO substitui testes funcionais manuais.

Implementação desejada (ajuste ao meu SDK — consulte documentação oficial da minha versão):
1. Se ausente, adicionar expo-build-properties compatível com meu expo no package.json (não inventar versão; usar mesma linha major do SDK).
2. Em app.json ou app.config, registrar plugin expo-build-properties com android.enableMinifyInReleaseBuilds: true. Não habilitar shrinkResources salvo documentação oficial e minha aprovação.
3. Para permissões confirmadas como desnecessárias, preferir android.blockedPermissions no Expo em vez de editar XML manual, salvo exceção justificada.
4. eas.json: se útil, criar ou ajustar perfil preview-optimized (extends preview, APK internal, autoIncrement coerente) para validar release otimizado antes do production AAB. Manter production como trilha do app bundle da loja (autoIncrement conforme projeto).
5. Mostrar diff arquivo a arquivo com uma linha de explicação cada. Sugerir mensagem de commit convencional (ex.: fix(android): …).
6. Listar comandos que EU executarei depois (npm install se necessário, eas build --profile …) — você NÃO executa build nem submit.

Após implementação no código (somente após minha OK em cada passo):
- Indicar testes estáticos disponíveis (npm run lint, npm test, tsc) se existirem no projeto.
- Listar fluxos manuais críticos para validar (notificações, telas principais, instalação limpa).

Entrega: diff proposto + sequência de validação; nenhum build automático.

Adaptar: confirme a versão do Expo no package.json antes de copiar; perfis EAS podem ter nomes diferentes — mantenha a separação testes internos (APK) vs loja (AAB production).

Prompt 4 — Validação e comprovação

Objetivo: Validar release otimizado (testes locais, comparação de artefatos, conferência Play Console), distinguindo tamanho do AAB, DEX dentro do bundle e download estimado — registrando limitações.

Versão revisada e reutilizável — no caso documentado, AAB 1.2.0 vs 1.3.0 mostrou queda na soma dos .dex (~44 MB → ~16 MB) e remoção de SYSTEM_ALERT_WINDOW no manifesto embarcado; métricas ~1% → ~92% de ofuscação e ~26,7 → ~16,7 MB de download são leituras do Play Console, não garantidas para outros projetos.

Pré-requisitos:

  • Artefato release anterior e novo (AAB e/ou APK) ou acesso somente leitura a cópias arquivadas.
  • Build de testes internos concluído (se aplicável) e build enviado ao Play identificado por versionName/versionCode.
  • Checklist funcional do app (fluxos críticos).
Prompt 4 — texto completo
Contexto: implementação de minificação release e ajustes de manifesto concluídos; preciso validar o release antes de confiar no Play Console.

Modo: VERIFICAÇÃO. Pode orientar comandos read-only; não publicar na Play nem executar submit sem minha aprovação.

1. Testes estáticos: rodar ou indicar npm run lint, npm test, typecheck se existirem; interpretar falhas relacionadas a minify/reflexão.

2. Comparação de artefatos (read-only):
   - Tamanho do arquivo .aab ou .apk (não confundir com download estimado na loja).
   - Quantidade e soma dos arquivos .dex dentro do AAB (zip/base/dex) — métrica técnica do bundle, não igual ao que cada usuário baixa.
   - Manifesto: permissões antes/depois (ex.: SYSTEM_ALERT_WINDOW presente ou ausente). Preferir bundletool/aapt2 se disponível; se não, declarar limitação da análise.
   - Deixar claro: % de ofuscação do Play ≠ % de redução de tamanho ≠ soma DEX.

3. Testes manuais no dispositivo (checklist): instalação limpa, fluxos que listo, notificações/alarmes se o app usa, regressões visuais. Minificação exige reteste — listar sinais de crash por ClassNotFound ou reflexão.

4. Google Play Console (orientação, sem pedir credenciais):
   - Onde encontrar relatório de otimização DEX / ofuscação e download estimado para a faixa publicada.
   - Tempo de processamento após upload; diferença entre versão em rascunho, teste fechado e produção.
   - Como comparar release anterior vs nova sem expor IDs de conta em material público.

5. Registro de resultados: tabela FATO (medidas locais que eu autorizar compartilhar) vs OBSERVAÇÃO PLAY (métricas do console em capturas sem dados sensíveis) vs EM ABERTO (itens só para documentação interna da equipe).

6. Limitações explícitas: validar com APK em perfil preview não prova sozinho o AAB production; versionCode pode diferir entre trilhas se autoIncrement/remote divergirem.

Entrega: relatório markdown curto para documentação interna + lista do que ainda falta evidenciar antes de artigo ou release notes públicas.

Adaptar: informe versionName/versionCode reais; substitua fluxos manuais pelos do seu app; arquive AABs fora do repositório público do site.

6. Implementação da correção

Na versão 1.3.0, o pipeline de release passou a aplicar R8 de forma efetiva no variant publicado e o manifesto deixou de declarar SYSTEM_ALERT_WINDOW — permissão típica de overlays flutuantes que o SimpleTaskFlow não utiliza.

Fluxo resumido (relato do caso PHR; reproduza no seu projeto com diff e builds próprios):

  1. Revisão do manifesto Android pós-prebuild / config Expo.
  2. Ajuste das flags de minificação/ofuscação no Gradle de release.
  3. Build de produção com EAS Build e upload de novo artefato ao Play Console.
  4. Incremento de versão (1.3.0) e notas de release internas.
Recomendação Documente no seu repositório qual perfil EAS e qual variant Gradle alimentam a faixa de produção no Play — evita corrigir um build de preview enquanto a loja serve outro.

7. Homologação e testes

Antes de confiar no relatório do Play, testamos manualmente notificações locais, navegação principal, cadastro de tarefas e instalação limpa do pacote release. Somente após estabilidade funcional acompanhamos o processamento das métricas de otimização no console (pode levar tempo após o upload).

As métricas da versão 1.2.0, antes da correção, estão na Figura 1.

Google Play Console — SimpleTaskFlow 1.3.0: otimização DEX alta, ofuscação 92%, R8 modo completo, DEX descompactado 16,4 MB; painel indica aceite a páginas de memória de 16 KB.

Abrir captura em tamanho maior

Figura 2 — Google Play Console: otimização DEX classificada como alta na versão 1.3.0, com 92% de ofuscação, R8 em modo completo e DEX descompactado de 16,4 MB.

8. Comparação antes e depois

Valores abaixo refletem observação no Google Play Console para o SimpleTaskFlow (releases 1.2.0 e 1.3.0). As Figuras 1 a 3 documentam métricas DEX e entrega na v1.3.0; o download estimado na v1.2.0 (~26,7 MB) é leitura anterior do console, sem figura de entrega equivalente neste artigo. Use como referência do caso, não como garantia para outros apps ou versões do Expo.

Resultado observado (Play Console — v1.3.0) Ofuscação 92%, avaliação DEX alta, DEX descompactado 16,4 MB (Figura 2). Novas instalações 16,7 MB e atualizações 6,49 MB (Figura 3).
Google Play Console — SimpleTaskFlow 1.3.0: tamanho para novas instalações 16,7 MB, tempo de download 9 s, tamanho das atualizações 6,49 MB.

Abrir captura em tamanho maior

Figura 3 — Google Play Console: entrega na versão 1.3.0 — 16,7 MB para novas instalações, tempo de download 9 s e 6,49 MB para atualizações.
Comparação SimpleTaskFlow 1.2.0 e 1.3.0 no Google Play
Métrica 1.2.0 (antes) 1.3.0 (depois)
Ofuscação (Play Console) 1% 92%
Avaliação otimização DEX Baixa (Figura 1) Alta (Figura 2)
DEX descompactado (Play Console) 46,5 MB (Figura 1) 16,4 MB (Figura 2)
Download (nova instalação) ~26,7 MB (observação Play Console na v1.2.0) 16,7 MB (Figura 3)
Tamanho das atualizações (Play Console) — (sem registro neste artigo para v1.2.0) 6,49 MB (Figura 3)
Configuração R8 (painel) Não informada (Figura 1) Modo completo (Figura 2)
R8 em release (projeto) Sem enableMinifyInReleaseBuilds (release 1.2.0) Habilitado (expo-build-properties; release 1.3.0)
SYSTEM_ALERT_WINDOW Presente no manifesto (release 1.2.0 — caso PHR) Ausente no manifesto (release 1.3.0 — caso PHR)

A redução de ~10 MB no download estimado não equivale à diferença de pontos percentuais de ofuscação (1% → 92%). São indicadores distintos do Play Console.

9. Cuidados, limitações e lições aprendidas

  • Métricas diferentes: ofuscação alta não “equivale” a X% menos MB; interprete cada indicador do Play separadamente.
  • Expo e versões: plugins, prebuild e defaults mudam entre SDKs; valide na documentação da sua versão (aqui: SDK 57).
  • IA como apoio: prompts aceleram o checklist; decisões de permissão e Gradle exigem revisão humana (diff e testes reais).
  • Permissões: remover entradas do manifesto sem entender a origem (app vs lib) pode quebrar plugins — teste fluxos críticos.
  • Privacidade na documentação: capturas do console podem expor conta e IDs; sanitizar antes de publicar evidências nesta página.
  • Páginas de memória 16 KB: na Figura 2, o Google Play Console indica “Aceita 16 KB” para o pacote analisado neste artigo (SimpleTaskFlow 1.3.0) — leitura pontual do painel, sem generalizar para outros dispositivos, versões do app ou requisitos técnicos de alinhamento nativo.
  • Requisitos futuros do Google: resolver o alerta DEX/ofuscação não implica atender automaticamente a todas as políticas ou métricas que o Play venha a exigir depois.

10. Referências e documentação oficial

Esta dica ajudou você?

Sua opinião nos ajuda a melhorar as soluções publicadas pela PHR Software.

Como você avalia esta dica?

Privacidade

Ao clicar em Enviar avaliação, seu aplicativo de e-mail será aberto com a mensagem preparada. Você poderá revisá-la antes de enviar.

Se enviar, a PHR Software receberá sua avaliação e seu endereço de e-mail. Seus dados serão utilizados somente para tratar sua avaliação e, se necessário, responder à sua mensagem. Não utilizamos seu e-mail para marketing ou envio de publicidade. Seus comentários não serão publicados no site.