Quando você ativa a otimização de apps com as configurações padrão, o R8 realiza otimizações extensas para maximizar os benefícios de desempenho. O R8 faz modificações substanciais no código, incluindo renomeação, movimentação e remoção de campos e métodos de classes. Se isso causar erros, você precisará especificar quais partes do código devem ser deixadas em paz, escrevendo regras keep.
O R8 pode remover ou modificar o código incorretamente nas seguintes situações:
- Reflexão: código acessado usando reflexão, por exemplo, usando
Class.forName()
ouMethod.invoke()
. O R8 geralmente não consegue informar quais classes ou métodos serão acessados dessa maneira. - Serialização: classes ou campos necessários para serialização e desserialização podem parecer não utilizados pelo R8 (essa é outra forma de reflexão).
- Java Native Interface (JNI): métodos Java chamados pelo código nativo. O R8 não analisa o código nativo para saber o que ele pode chamar de volta no Java.
Esta página aborda como limitar a extensão das otimizações do R8. Para saber como personalizar quais recursos são mantidos, consulte Adicionar regras de manutenção de recursos.
Onde adicionar regras de manutenção
Adicione as regras a um arquivo proguard-rules.pro
localizado no
diretório raiz do módulo. O arquivo pode já estar lá, mas, se não estiver,
crie-o. Para aplicar as regras no arquivo, declare-o no
arquivo build.gradle.kts
(ou build.gradle
) no nível do módulo, conforme mostrado no
código abaixo:
Kotlin
android { buildTypes { release { isMinifyEnabled = true isShrinkResources = true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile("proguard-android-optimize.txt"), // File with your custom rules. "proguard-rules.pro" ) ... } } ... }
Groovy
android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile('proguard-android-optimize.txt'), // File with your custom rules. 'proguard-rules.pro' ) } } // ... }
Por padrão, o script de build também inclui o arquivo
proguard-android-optimize.txt
. Esse arquivo inclui regras necessárias para a maioria dos projetos do Android.
Portanto, mantenha-o no script de build.
Como escrever regras de manutenção
Durante a compilação do app, o R8 detecta qual código precisa ser mantido em um app analisando o gráfico de chamadas do app, que começa nas entradas do manifesto (como atividades ou serviços) e rastreia todas as chamadas de função de app e biblioteca. O R8 remove o código que não é referenciado diretamente dessa maneira, o que pode causar problemas se o código executado não fizer parte desse gráfico, por exemplo, código invocado por reflexão. Ao escrever suas próprias regras keep, você pode informar ao R8 o código que precisa permanecer no app.
Para adicionar uma regra de manutenção, adicione uma linha -keep
no arquivo proguard-rules.pro
.
Sintaxe de regra de manter
As regras de armazenamento geralmente seguem este formato:
-<KeepOption> [OptionalModifier,...] <ClassSpecification> [{ OptionalMemberSpecification }]
Por exemplo, para preservar uma classe específica e todos os membros dela, use o seguinte:
-keep class com.myapp.MyClass { *; }
Para mais exemplos, consulte a seção de exemplos.
Confira o que os componentes da regra de manutenção fazem:
<KeepOption>
permite especificar quais aspectos de uma classe preservar:Opção "Manter" Descrição -keep
Preserve a classe e os membros listados em
[{ OptionalMemberSpecification }]
.-keepclassmembers
Permite a otimização da classe. Se a classe for preservada, os membros listados em
[{ OptionalMemberSpecification }]
também serão.-keepnames
Permite a remoção de classes e membros, mas não ofusca ou modifica de outras maneiras.
-keepclassmembernames
Permita a remoção de classes e membros, mas não ofusque nem modifique membros de outras maneiras.
-keepclasseswithmembers
Não há remoção ou ofuscação de classes se os membros corresponderem ao padrão especificado.
Recomendamos o uso de
-keepclassmembers
, já que ele permite a maioria dos otimizações, e depois-keepnames
, se necessário. O-keep
não permite otimizações. Portanto, use-o com moderação.[OptionalModifier],...]
permite listar zero ou mais modificadores de linguagem Java de uma classe, por exemplo,public
oufinal
.<ClassSpecification>
permite especificar a qual classe (ou qual superclasse ou interface implementada) a regra de manutenção será aplicada. No caso mais simples, essa é uma classe totalmente qualificada.[{ OptionalMemberSpecification }]
permite filtrar o comportamento de retenção para apenas classes e métodos que correspondem a determinados padrões. Em geral, isso é recomendado na maioria das regras de retenção para evitar a retenção de mais itens do que o pretendido.
Exemplos de regras do Keep
Confira alguns exemplos de regras de manutenção bem projetadas.
Criar subclasse
Essa regra de manutenção é empacotada dentro de androidx.room:room-runtime
para manter
os construtores de banco de dados instanciados por reflexão.
-keep class * extends androidx.room.RoomDatabase { void <init>(); }
Reflexão do framework do Android ObjectAnimator
Essa regra de manutenção é
empacotada dentro de androidx.vectordrawable:vectordrawable-animated
para
permitir que ObjectAnimator
chame getters ou setters do código nativo com
JNI. Os sistemas de animação mais recentes no Compose não exigem regras de manutenção como
essa. É apenas um exemplo de estrutura de regra.
-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* {
void set*(***);
*** get*();
}
Registro de JNI
Essa regra de manutenção é empacotada dentro de androidx.graphics:graphics-path
,
usada para manter métodos nativos. Isso pode ser necessário se a biblioteca registrar manualmente
métodos nativos com env->RegisterNatives()
.
-keepclasseswithmembers class androidx.graphics.path.** {
native <methods>;
}