Usar recursos e APIs da linguagem Java 8

O Plug-in do Android para Gradle 3.0.0 e versões mais recentes oferece suporte a todos os recursos da linguagem Java 7 e a um subconjunto de recursos da linguagem Java 8 que variam de acordo com a versão da plataforma. Ao criar seu app usando o Plug-in do Android para Gradle 4.0.0 e versões mais recentes, você pode usar algumas APIs da linguagem Java 8 sem exigir um nível mínimo da API para o app.

Esta página descreve os recursos da linguagem Java 8 que você pode usar, como configurar seu projeto corretamente para usá-los e possíveis problemas conhecidos. Confira o vídeo abaixo para ter uma visão geral dos recursos da linguagem Java 8.

O Plug-in do Android para Gradle oferece suporte para alguns recursos da linguagem Java 8 e algumas bibliotecas de terceiros que os utilizam. O conjunto de ferramentas padrão implementa os novos recursos da linguagem, executando transformações de bytecode, denominadas desugar, como parte da compilação D8/R8 de arquivos de classe em código DEX, como mostrado na Figura 1.

Suporte a recursos da linguagem Java 8 usando transformações de bytecode
    simplificadas ("desugar").
Figura 1. Suporte a recursos da linguagem Java 8 usando transformações de bytecode desugar.

Suporte a recursos da linguagem Java 8 (Plug-in do Android para Gradle 3.0.0+)

Para começar a usar os recursos da linguagem Java 8 com suporte:

  1. Atualize o Plug-in do Android para Gradle para a versão 3.0.0 ou mais recente.
  2. Para cada módulo que usa recursos da linguagem Java 8 (no código-fonte ou por dependências), atualize o arquivo build.gradle ou build.gradle.kts do módulo, conforme mostrado abaixo.

Kotlin

android {
    ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Groovy

android {
    ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Ao criar seu app usando o Plug-in do Android para Gradle 3.0.0 e versões mais recentes, o plug-in não oferece suporte a todos os recursos da linguagem Java 8. Os recursos de linguagem abaixo estão disponíveis em qualquer nível da API:

Recurso da linguagem Java 8 Observações
Expressões lambda (link em inglês) O Android não oferece suporte à serialização de expressões lambda.
Referências de métodos (link em inglês)  
Anotações de tipo (link em inglês) As informações de anotação de tipo só estão disponíveis durante a compilação e não durante a execução. A plataforma oferece suporte a TYPE na API de nível 24 ou anterior, mas não oferece suporte a ElementType.TYPE_USE ou ElementType.TYPE_PARAMETER.
Métodos de interface padrão e estáticos (link em inglês)  
Repetição de anotações (link em inglês)  

Além desses recursos da linguagem Java 8, o Plug-in do Android para Gradle versão 3.0.0 e mais recentes estende o suporte a try-with-resources (link em inglês) para todos os níveis de API do Android.

A simplificação não oferece suporte a MethodHandle.invoke ou MethodHandle.invokeExact (links em inglês). Se o código-fonte ou uma das dependências do módulo usa um desses métodos, é necessário especificar minSdkVersion 26 ou uma versão mais recente. Caso contrário, este erro ocorre:

Dex: Error converting bytecode to dex:
Cause: signature-polymorphic method called without --min-sdk-version >= 26

Em alguns casos, o módulo pode não usar os métodos invoke ou invokeExact, mesmo se incluídos em uma dependência de biblioteca. Para continuar usando essa biblioteca com minSdkVersion 25 ou versões anteriores, ative a redução de código para remover os métodos não usados. Se isso não funcionar, use outra biblioteca que não utilize os métodos sem suporte.

Os recursos da linguagem Java 8+ no Plug-in do Android para Gradle 3.0.0 e versões mais recentes não disponibilizam outras classes e APIs (como java.util.stream.*) para uso em versões mais antigas do Android. O suporte a simplificação parcial da API Java está disponível no Plug-in do Android para Gradle 4.0.0 ou mais recente e é descrito na próxima seção.

Suporte para a simplificação de APIs do Java 8+ (Plug-in do Android para Gradle 4.0.0+)

Se você estiver criando o app usando o Plug-in do Android para Gradle 4.0.0 ou versões mais recentes, o plug-in vai ampliar o suporte para o uso de diversas APIs da linguagem Java 8 sem exigir um nível mínimo de API para o app. Com o Plug-in do Android para Gradle 7.4.0 ou versões mais recentes, várias APIs da linguagem Java 11 também estão disponíveis com a biblioteca simplificada de 2.0.0 ou mais recente.

Esse suporte extra a versões de plataforma mais antigas é possível porque o plug-in 4.0.0 e versões mais recentes ampliam o mecanismo de simplificação para funcionar com as APIs da linguagem Java. Você pode incluir APIs de linguagem padrão que estavam disponíveis apenas em versões recentes do Android (por exemplo, java.util.streams) em apps com suporte a versões mais antigas do Android.

O seguinte conjunto de APIs oferece suporte para a criação do app usando o Plug-in do Android para Gradle 4.0.0 ou versões mais recentes:

  • Fluxos sequenciais (java.util.stream)
  • Um subconjunto de java.time
  • java.util.function
  • Adições recentes a java.util.{Map,Collection,Comparator}
  • Recursos opcionais (java.util.Optional, java.util.OptionalInt e java.util.OptionalDouble) e algumas novas classes
  • Algumas adições a java.util.concurrent.atomic (novos métodos em AtomicInteger, AtomicLong e AtomicReference)
  • ConcurrentHashMap (com correções de bugs para o Android 5.0)

Com o Plug-in do Android para Gradle 7.4.0 ou versões mais recentes, outras APIs Java 11 têm suporte, como um subconjunto do pacote java.nio.file.

Para conferir uma lista completa das APIs com suporte, acesse APIs Java 8+ disponíveis pela simplificação e APIs Java 11+ disponíveis pela simplificação.

Para oferecer suporte a essas APIs de linguagem, o plug-in compila um arquivo DEX separado que contém uma implementação das APIs ausentes e as inclui no app. O processo de simplificação reescreve o código do app para usar essa biblioteca durante a execução.

Para ativar o suporte a essas APIs de linguagem em qualquer versão da plataforma Android:

  1. Atualize o Plug-in do Android para Gradle para a versão 4.0.0 (ou mais recente).
  2. Inclua o seguinte no arquivo build.gradle ou build.gradle.kts do módulo do app:

Kotlin

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled = true
    }

    compileOptions {
        // Flag to enable support for the new language APIs

        // For AGP 4.1+
        isCoreLibraryDesugaringEnabled = true
        // For AGP 4.0
        // coreLibraryDesugaringEnabled = true

        // Sets Java compatibility to Java 8
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    // For AGP 7.4+
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
    // For AGP 7.3
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.3")
    // For AGP 4.0 to 7.2
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.9")
}

Groovy

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled true
    }

    compileOptions {
        // Flag to enable support for the new language APIs
        coreLibraryDesugaringEnabled true
        // Sets Java compatibility to Java 8
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    // For AGP 7.4+
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
    // For AGP 7.3
    // coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.3'
    // For AGP 4.0 to 7.2
    // coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.9'
}

Também pode ser necessário incluir o snippet de código acima em um arquivo build.gradle ou build.gradle.kts do módulo da biblioteca se:

  • Os testes de instrumentação do módulo da biblioteca usam essas APIs de linguagem, seja diretamente pelo módulo da biblioteca ou pelas dependências dele. Dessa forma, as APIs que não estiverem presentes vão ser fornecidas para o APK de teste de instrumentação.

  • você quer executar o lint no módulo da biblioteca de forma isolada. O objetivo é ajudar o lint a reconhecer usos válidos das APIs de linguagem e evitar avisos falsos.

Além disso, a simplificação de APIs pode ser combinada com a redução, mas apenas ao usar o redutor R8.

Versões

A tabela abaixo mostra as versões da biblioteca de APIs do Java 8 e versões mais recentes, além da versão mínima do Plug-in do Android para Gradle com suporte para cada versão.

Versão Versão mínima do Plug-in do Android para Gradle
1.1,9 4.0.0
1.2,3 7.3.0
2.0.3 7.4.0-alpha10

Para mais detalhes sobre as versões da biblioteca de APIs do Java 8 e versões mais recentes, consulte o arquivo CHANGELOG.md (link em inglês) no repositório desugar_jdk_libs do GitHub.