Utilizzo di funzionalità e API del linguaggio Java 8

Il plug-in Android per Gradle 3.0.0 e versioni successive supporta tutte le funzionalità del linguaggio Java 7 e un sottoinsieme di funzionalità del linguaggio Java 8 che variano a seconda della versione della piattaforma. Quando crei la tua app utilizzando il plug-in Android per Gradle 4.0.0 e versioni successive, puoi utilizzare alcune API in linguaggio Java 8 senza richiedere un livello API minimo per l'app.

Questa pagina descrive le funzionalità del linguaggio Java 8 che puoi utilizzare, come configurare correttamente il tuo progetto per il loro utilizzo e gli eventuali problemi noti che potresti riscontrare. Guarda il video che segue per una panoramica delle funzionalità del linguaggio Java 8.

Il plug-in Android per Gradle fornisce supporto integrato per l'utilizzo di determinate funzionalità del linguaggio Java 8 e delle librerie di terze parti che le utilizzano. La Toolchain predefinita implementa le nuove funzionalità del linguaggio eseguendo trasformazioni di bytecode, chiamate desugar, come parte della compilazione D8/R8 dei file delle classi in codice DEX, come mostrato nella Figura 1.

Supporto delle funzionalità del linguaggio Java 8 mediante trasformazioni di bytecode "desugar"
Figura 1. Supporto delle funzionalità del linguaggio Java 8 mediante trasformazioni bytecode desugar.

Supporto delle funzionalità del linguaggio Java 8 (plug-in Android Gradle 3.0.0 e versioni successive)

Per iniziare a utilizzare le funzionalità del linguaggio Java 8 supportate:

  1. Aggiorna il plug-in Android per Gradle alla versione 3.0.0 o successiva.
  2. Per ogni modulo che utilizza le funzionalità del linguaggio Java 8 (nel codice sorgente o tramite dipendenze), aggiorna il file build.gradle o build.gradle.kts del modulo come mostrato di seguito:

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

Trendy

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

Quando crei la tua app utilizzando il plug-in Android per Gradle 3.0.0 e versioni successive, il plug-in non supporta tutte le funzionalità del linguaggio Java 8. Le seguenti funzionalità linguistiche sono disponibili per qualsiasi livello API:

Funzionalità del linguaggio Java 8 Notes
Espressioni lambda Android non supporta la serializzazione delle espressioni lambda.
Riferimenti al metodo  
Annotazioni del tipo Le informazioni sull'annotazione del tipo sono disponibili solo in fase di compilazione, non in fase di runtime. La piattaforma supporta TYPE nel livello API 24 e precedenti, ma non in ElementType.TYPE_USE o ElementType.TYPE_PARAMETER.
Metodi di interfaccia predefiniti e statici  
Ripetizione delle annotazioni  

Oltre a queste funzionalità del linguaggio Java 8, le versioni del plug-in Android per Gradle 3.0.0 e versioni successive estendono il supporto per try-with-resources a tutti i livelli dell'API Android.

Desugar non supporta MethodHandle.invoke o MethodHandle.invokeExact. Se il codice sorgente o una delle dipendenze del modulo utilizza uno di questi metodi, devi specificare minSdkVersion 26 o un valore superiore. In caso contrario, riceverai il seguente errore:

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

In alcuni casi, il modulo potrebbe non utilizzare i metodi invoke o invokeExact anche se sono inclusi in una dipendenza della libreria. Per continuare a utilizzare la libreria con minSdkVersion 25 o un livello precedente, attiva la riduzione del codice per rimuovere i metodi non utilizzati. Se questa soluzione non funziona, valuta la possibilità di utilizzare una libreria alternativa che non utilizza i metodi non supportati.

Le funzionalità del linguaggio Java 8 e versioni successive che eseguono il deprovisioning del plug-in Android per Gradle 3.0.0 e versioni successive e non rendono disponibili per l'utilizzo su release precedenti di Android classi e API aggiuntive, ad esempio java.util.stream.*. Il supporto per il deprovisioning parziale dell'API Java è disponibile dal plug-in Android Gradle 4.0.0 o versioni successive, come descritto nella sezione seguente.

Supporto del desugaring dell'API Java 8 e versioni successive (plug-in Android Gradle 4.0.0 e versioni successive)

Se crei la tua app utilizzando il plug-in Android per Gradle 4.0.0 o versioni successive, il plug-in estende il supporto per l'utilizzo di una serie di API in linguaggio Java 8 senza richiedere un livello API minimo per l'app. Con il plug-in Android per Gradle 7.4.0 o versione successiva, sono disponibili anche diverse API in linguaggio Java 11 con desugared 2.0.0 o versioni successive.

Questo supporto aggiuntivo per le versioni precedenti della piattaforma è possibile perché il plug-in 4.0.0 e versioni successive estende il motore di desugaring in modo da eliminare anche le API del linguaggio Java. Puoi includere API di lingua standard disponibili solo nelle release recenti di Android (ad esempio java.util.streams) nelle app che supportano le versioni precedenti di Android.

Il seguente set di API è supportato quando crei la tua app utilizzando il plug-in Android Gradle 4.0.0 o versioni successive:

  • Stream sequenziali (java.util.stream)
  • Un sottoinsieme di java.time
  • java.util.function
  • Aggiunte recenti a java.util.{Map,Collection,Comparator}
  • Facoltativo (java.util.Optional, java.util.OptionalInt e java.util.OptionalDouble) e alcuni nuovi corsi
  • Alcune aggiunte a java.util.concurrent.atomic (nuovi metodi su AtomicInteger, AtomicLong e AtomicReference)
  • ConcurrentHashMap (con correzioni di bug per Android 5.0)

Con il plug-in Android per Gradle 7.4.0 o versioni successive, sono supportate API Java 11 aggiuntive, ad esempio un sottoinsieme del pacchetto java.nio.file.

Per un elenco completo delle API supportate, consulta le pagine API Java 8 e versioni successive disponibili tramite desugaring e API Java 11 o versioni successive disponibili tramite desugaring.

Per supportare queste API di linguaggio, il plug-in compila un file DEX separato che contiene un'implementazione delle API mancanti e la include nella tua app. Il processo di rimozione riscrive il codice dell'app in modo che utilizzi questa libreria in fase di runtime.

Per attivare il supporto di queste API di linguaggio su qualsiasi versione della piattaforma Android:

  1. Aggiorna il plug-in Android per Gradle alla versione 4.0.0 (o successiva).
  2. Includi quanto segue nel file build.gradle o build.gradle.kts del modulo dell'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")
}

Trendy

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

Tieni presente che potrebbe essere necessario anche includere lo snippet di codice precedente nel file build.gradle o build.gradle.kts del modulo della libreria se:

  • I test strumentati del modulo della libreria utilizzano queste API di linguaggio (direttamente o tramite il modulo della libreria o le sue dipendenze). In questo modo, vengono fornite le API mancanti per l'APK di test strumentato.

  • Vuoi eseguire lint sul modulo della libreria in modo isolato. Questo serve a consentire a lint di riconoscere gli utilizzi validi delle API di linguaggio ed evitare di segnalare falsi avvisi.

Tieni inoltre presente che il deprovisioning delle API può essere combinato con la riduzione, ma solo quando si utilizza lo shrinker R8.

Versions

La seguente tabella mostra le versioni della libreria API Java 8 e versioni successive e la versione minima del plug-in Android Gradle che supporta ogni versione:

Versione Versione minima del plug-in Android per Gradle
1.1.9 4,0,0
1.2.3 7.3.0
2,0,3 7.4.0-alpha10

Per maggiori dettagli sulle versioni della libreria API Java 8 e versioni successive, consulta il file CHANGELOG.md nel repository GitHub di desugar_jdk_libs.