Sobre as regras de retenção

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 classes, campos e métodos. Se você notar que essas modificações causam erros, especifique quais partes do código o R8 não deve modificar declarando-as nas regras de manutenção.

Cenários comuns que exigem regras de manutenção

O R8 identifica e preserva todas as chamadas diretas no seu código. No entanto, o R8 não consegue ver usos indiretos de código, o que pode fazer com que ele remova códigos necessários para o app, causando falhas. Use regras de manutenção para instruir o R8 a preservar esse código usado indiretamente. Veja algumas situações comuns em que você provavelmente precisará de regras de manutenção:

  • Código acessado por reflexão: o R8 não consegue identificar quando classes, campos ou métodos são acessados com reflexão. Por exemplo, o R8 não pode identificar um método pesquisado pelo nome usando Class.getDeclaredMethod() ou uma anotação recuperada com Class.getAnnotation(). Nesses casos, o R8 pode renomear esses métodos e anotações ou removê-los completamente, o que leva a uma ClassNotFoundException ou uma NoSuchMethodException no momento da execução.
  • Código chamado pela Java Native Interface (JNI): quando o código nativo (C ou C++) chama um método Java ou Kotlin, ou o código Java ou Kotlin chama o código C++ com a JNI, a chamada é baseada em uma pesquisa de string dinâmica do nome do método. O R8 não consegue ver a chamada de método dinâmica baseada em string, então as otimizações dele podem corromper seu código.

Esta não é uma lista completa de cenários que exigem regras de manutenção, mas eles abrangem a maioria dos casos em que você pode precisar delas.

Se o código usa reflexão ou é chamado pela JNI, é possível usar as anotações do Jetpack Keep em vez de escrever regras keep manualmente. O plug-in do Gradle gera as regras de manutenção com base nas anotações no momento do build.

Entender como as regras de manutenção afetam a otimização

O R8 é um otimizador de programa completo que analisa o código do app para remover códigos não utilizados, métodos inline, mesclar classes e ofuscar identificadores. No entanto, o R8 só pode otimizar dentro da configuração que você define.

As regras de manutenção representam uma instrução explícita para limitar a otimização. Cada regra de manutenção declarada restringe a capacidade do R8 de transformar essa parte da base de código. O valor de uma regra de retenção bem elaborada está na especificidade:

  • As regras de manutenção restritas permitem a otimização máxima: ao segmentar apenas os pontos de entrada exatos acessados dinamicamente (como um construtor reflexivo ou um campo serializado), você permite que o R8 otimize o restante do código.

  • Regras de manutenção amplas impedem a otimização: declarar regras em todo o pacote ou caracteres curinga amplos impede que o R8 otimize classes inteiras e todos os membros delas. O R8 não pode remover, inline, mesclar ou ofuscar esse código.

Regras de manutenção excessivamente amplas levam diretamente a binários DEX inchados, maior consumo de memória do app, tempos de inicialização mais lentos (TTID e TTFD) e taxas de ANR mais altas. Sua meta não deve ser manter as classes "por precaução", mas definir o contrato mínimo necessário para a execução dinâmica.

Para encontrar regras de manutenção amplas ou desnecessárias, incluindo as de bibliotecas de terceiros, use o R8 Configuration Analyzer. Ele informa as pontuações de redução, otimização e ofuscação que mostram quanto do seu código o R8 pode otimizar.

Como adicionar regras de manutenção ao app

A configuração das regras de manutenção depende da versão do AGP que você usa.

Os apps maiores geralmente têm código em vários módulos de biblioteca. Nesses casos, geralmente é melhor colocar as regras de manutenção junto ao código a que elas se aplicam no módulo de biblioteca específico. A diferença crucial na manutenção de regras de preservação para bibliotecas está na forma como você declara essas regras no arquivo build.gradle.kts (ou build.gradle) do módulo da biblioteca. Consulte Otimização para autores de bibliotecas para saber mais.

Para as versões 9.3 e mais recentes do AGP

Adicione as regras a um arquivo com o sufixo .keep no diretório src/<variant>/keepRules. Por exemplo, src/main/keepRules/custom-rules.keep. O uso da DSL atualizada para o AGP 9.3 e versões mais recentes permite a otimização de código e de recursos e não exige que você defina explicitamente o arquivo de regras de manutenção padrão do Android (proguard-android-optimize.txt), porque ele é incluído por padrão, a menos que seja omitido explicitamente.

Kotlin

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
            }
        }
    }
}

Groovy

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
            }
        }
    }
}

Omitir as regras de manutenção padrão da plataforma Android (avançado)

O AGP fornece um conjunto de regras padrão da plataforma Android. Para omitir essas regras da configuração do projeto e gerenciar todas as regras de manutenção por conta própria, defina optimization.keepRules.includeDefault como false.

Kotlin

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
                keepRules {
                    includeDefault = false // The file with optimization
                    // rules for the Android platform is included by
                    // default. To omit this file, set this option to false.
                }
            }
        }
    }
}

Groovy

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
                keepRules {
                    includeDefault = false // The file with optimization
                    // rules for the Android platform is included by
                    // default. To omit this file, set this option to false.
                }
            }
        }
    }
}

DSL legado para versões do AGP anteriores à 9.3

Adicione as regras a um arquivo proguard-rules.pro localizado no diretório raiz do módulo do app. 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) do módulo.

Por padrão, o arquivo 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 arquivo de build. Este arquivo é baseado no arquivo proguard-common.txt e compartilha conteúdo com ele.

DSL legada (Kotlin)

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true

            proguardFiles(
                // Default file with default optimization rules.
                getDefaultProguardFile("proguard-android-optimize.txt"),
                ...
            )
        }
    }
}

DSL legado (Groovy)

android {
    buildTypes {
        release {
            minifyEnabled = true
            shrinkResources = true

            // Default file with default optimization rules.
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
            ...
        }
    }
}

Adicionar uma regra de retenção

Ao adicionar regras de manutenção, você pode incluir opções globais e definir suas próprias regras.

  • Opções globais: são diretivas gerais que afetam como o R8 opera em toda a base de código. Para saber mais, consulte Opções globais.

  • Regras de retenção: precisam ser projetadas com cuidado para garantir o equilíbrio certo entre maximizar a otimização do código sem corromper o app acidentalmente. Para saber como escrever regras de retenção, consulte Adicionar regras de retenção.

Regras de manutenção para autores de bibliotecas

Depois de aprender sobre as opções globais e a sintaxe das regras de manutenção, consulte Otimização para autores de bibliotecas para mais detalhes.