Utiliser les API et les fonctionnalités du langage Java 8

Le plug-in Android Gradle 3.0.0 ou version ultérieure est compatible avec toutes les fonctionnalités du langage Java 7 et avec un sous-ensemble de fonctionnalités du langage Java 8, qui varie selon la version de la plate-forme. Si vous compilez votre application à l'aide du plug-in Android Gradle 4.0.0 ou version ultérieure, vous pouvez utiliser un certain nombre d'API en langage Java 8 sans avoir à définir un niveau d'API minimal pour votre application.

Cette page décrit les fonctionnalités du langage Java 8 dont vous pouvez vous servir et explique comment configurer correctement votre projet pour les utiliser. Vous verrez également les problèmes connus que vous pouvez rencontrer. La vidéo ci-dessous vous offre un aperçu des fonctionnalités de Java 8.

Le plug-in Android Gradle est compatible avec l'utilisation de certaines fonctionnalités du langage Java 8 et des bibliothèques tierces qui les utilisent. La chaîne d'outils par défaut implémente les fonctionnalités du nouveau langage en effectuant des transformations bytecode, appelées desugar, dans le cadre de la compilation D8/R8 des fichiers de classe en code DEX, comme illustré dans la figure 1.

Compatibilité des fonctionnalités du langage Java 8 avec les transformations bytecode "desugar"
Figure 1. Compatibilité des fonctionnalités du langage Java 8 avec les transformations bytecode desugar

Compatibilité avec les fonctionnalités du langage Java 8 (plug-in Android Gradle 3.0.0 et versions ultérieures)

Pour utiliser les fonctionnalités compatibles du langage Java 8, procédez comme suit :

  1. Mettez à jour le plug-in Android Gradle vers la version 3.0.0 ou une version ultérieure.
  2. Mettez à jour le fichier build.gradle ou build.gradle.kts pour chaque module qui utilise les fonctionnalités Java 8 (dans son code source ou via des dépendances), comme indiqué ci-dessous :

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"
    }
}

Si vous compilez votre application à l'aide du plug-in Android Gradle 3.0.0 ou version ultérieure, certaines fonctionnalités du langage Java 8 ne seront pas prises en charge. Les fonctionnalités suivantes sont disponibles à tous les niveaux d'API :

Fonctionnalité du langage Java 8 Notes
Expressions lambda Android n'est pas compatible avec la sérialisation des expressions lambda.
Références de méthode  
Annotations de type Les informations d'annotation de type ne sont disponibles qu'au moment de la compilation, et non lors de l'exécution. De plus, la plate-forme prend en charge TYPE pour les niveaux d'API 24 et inférieurs, mais pas ElementType.TYPE_USE ni ElementType.TYPE_PARAMETER.
Méthodes d'interface statiques et par défaut  
Répétition des annotations  

En plus des fonctionnalités du langage Java 8 ci-dessus, les versions de plug-in Android Gradle 3.0.0 et versions ultérieures étendent la compatibilité avec try-with-resources à tous les niveaux d'API Android.

Desugar n'est pas compatible avec MethodHandle.invoke ni avec MethodHandle.invokeExact. Si votre code source ou l'une de vos dépendances de module utilise l'une de ces méthodes, vous devez spécifier minSdkVersion 26 ou une version ultérieure. Dans le cas contraire, vous obtenez l'erreur suivante :

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

Dans certains cas, il est possible que votre module n'utilise pas les méthodes invoke ou invokeExact, même lorsqu'elles sont incluses dans une dépendance de bibliothèque. Pour continuer à utiliser cette bibliothèque avec minSdkVersion 25 ou une version antérieure, activez la minification de code afin de supprimer les méthodes non utilisées. Si cela ne fonctionne pas, envisagez d'avoir recours à une autre bibliothèque qui n'utilise pas de méthodes non compatibles.

Le désucrage des fonctionnalités du langage Java 8 ou version ultérieure avec le plug-in Android Gradle 3.0.0 ou version ultérieure ne permet pas d'utiliser des classes et des API supplémentaires (telles que java.util.stream.*) sur les anciennes versions d'Android. Le désucrage partiel des API Java est disponible à partir de la version 4.0.0 du plug-in Android Gradle. Ce processus est décrit dans la section suivante.

Compatibilité du désucrage d'API avec Java 8 ou version ultérieure (plug-in Android Gradle 4.0.0 et versions ultérieures)

Si vous compilez votre appli à l'aide du plug-in Android Gradle 4.0.0 ou version ultérieure, vous pouvez utiliser un certain nombre d'API en langage Java 8 sans avoir à définir un niveau d'API minimal pour votre appli. Avec le plug-in Android Gradle 7.4.0 ou version ultérieure, plusieurs API en langage Java 11 sont également disponibles avec la bibliothèque désucrée 2.0.0 ou ultérieure.

Cette compatibilité supplémentaire avec les anciennes versions de plate-forme est rendue possible par le fait que les versions 4.0.0 et ultérieures du plug-in étendent le moteur de désucrage aux API en Java. Cela vous permet d'inclure des API en langage standard qui n'étaient disponibles que dans les versions récentes d'Android (telles que java.util.streams) dans les applications compatibles avec d'anciennes versions.

Les API suivantes sont compatibles avec la version 4.0.0 ou ultérieure du plug-in Android Gradle :

  • Flux séquentiels (java.util.stream)
  • Un sous-ensemble de java.time
  • java.util.function
  • Ajouts récents à java.util.{Map,Collection,Comparator}
  • Options (java.util.Optional, java.util.OptionalInt et java.util.OptionalDouble) et certaines nouvelles classes
  • Ajouts à java.util.concurrent.atomic (nouvelles méthodes sur AtomicInteger, AtomicLong et AtomicReference)
  • ConcurrentHashMap (avec corrections de bugs pour Android 5.0)

Avec le plug-in Android Gradle 7.4.0 ou version ultérieure, d'autres API Java 11 sont compatibles, telles qu'un sous-ensemble du package java.nio.file.

Pour obtenir la liste complète des API compatibles, consultez les pages API Java 8 et versions ultérieures disponibles via le désucrage et API Java 11 et versions ultérieures disponibles via le désucrage.

Pour prendre en charge ces API de langage, le plug-in compile un fichier DEX distinct qui contient une implémentation des API manquantes et l'inclut dans votre appli. Le processus de désucrage réécrit le code de votre appli pour utiliser à la place cette bibliothèque lors de l'exécution.

Pour activer la compatibilité avec ces API de langage sur n'importe quelle version de la plate-forme Android, procédez comme suit :

  1. Mettez à jour le plug-in Android Gradle vers la version 4.0.0 ou une version ultérieure.
  2. Incluez les éléments suivants dans le fichier build.gradle ou build.gradle.kts de votre module d'application :

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'
}

Notez que vous devrez peut-être également ajouter l'extrait de code ci-dessus dans le fichier build.gradle ou build.gradle.kts d'un module de bibliothèque dans les cas suivants :

  • Les tests instrumentés du module de bibliothèque utilisent des API reposant sur ce langage (soit directement, soit via le module de bibliothèque ou ses dépendances). Cela permet de fournir les API manquantes pour votre APK de test instrumenté.

  • Vous souhaitez exécuter lint sur le module de la bibliothèque de manière isolée. Cela permet à lint d'identifier les utilisations valides des API de langage et d'éviter de signaler de faux avertissements.

Notez également que le désucrage d'API peut être associé à la minification, mais uniquement lorsque vous utilisez R8.

Versions

Le tableau suivant présente les versions de la bibliothèque d'API Java 8 ou version ultérieure ainsi que la version minimale du plug-in Android Gradle compatible avec chaque version :

Version Version minimale du plug-in Android Gradle
1.1.9 4.0.0
1.2.3 7.3.0
2.0.3 7.4.0-alpha10

Pour en savoir plus sur les versions de la bibliothèque d'API Java 8 ou version ultérieure, consultez le fichier CHANGELOG.md dans le dépôt GitHub desugar_jdk_libs.