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 delle funzionalità del linguaggio Java 8 che variano in base alla versione della piattaforma. Quando crei la tua app utilizzando il plug-in Android Gradle 4.0.0 e versioni successive, puoi utilizzare alcune API di linguaggio Java 8 senza richiedere un livello API minimo per la tua app.

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

Il plug-in Gradle per Android fornisce il 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 del bytecode, chiamate desugar, nell'ambito della compilazione D8/R8 dei file di classe in codice DEX, come mostrato nella figura 1.

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

Supporto delle funzionalità del linguaggio Java 8 (plug-in Android per 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 successive.
  2. Per ogni modulo che utilizza le funzionalità del linguaggio Java 8 (nel codice sorgente o tramite le dipendenze), aggiornate 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"
    }
}

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

Quando crei l'app utilizzando il plug-in Android 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 a qualsiasi livello di API:

Funzionalità del linguaggio Java 8 Note
Espressioni lambda Android non supporta la serializzazione delle espressioni lambda.
Riferimenti ai metodi  
Annotazioni del tipo Le informazioni sulle annotazioni dei tipi sono disponibili solo in fase di compilazione, non in fase di esecuzione. La piattaforma supporta TYPE a livello di API 24 e versioni precedenti, ma non ElementType.TYPE_USE o ElementType.TYPE_PARAMETER.
Metodi di interfaccia predefiniti e statici  
Annotazioni ripetute  

Oltre a queste funzionalità del linguaggio Java 8, le versioni 3.0.0 e successive del plug-in Android per Gradle estendono il supporto per try-with-resources a tutti i livelli 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 versioni successive. 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 versioni precedenti, attiva la riduzione del codice per rimuovere i metodi inutilizzati. Se il problema persiste, valuta la possibilità di utilizzare una libreria alternativa che non utilizzi i metodi non supportati.

Le funzionalità di desugaring del linguaggio Java 8 e versioni successive sono disponibili nel plug-in Android Gradle 3.0.0 e versioni successive e non rendono disponibili classi e API aggiuntive (come java.util.stream.*) per le release Android precedenti. Il supporto per la desugaring parziale delle API Java è disponibile dal plug-in Android Gradle 4.0.0 o versioni successive, come descritto nella sezione seguente.

Supporto per il desugaring delle API Java 8 e versioni successive (Android Gradle Plugin 4.0.0 e versioni successive)

Se stai creando la tua app utilizzando il plug-in Android Gradle 4.0.0 o versioni successive, il plug-in estende il supporto per l'utilizzo di una serie di API di linguaggio Java 8 senza richiedere un livello API minimo per l'app. Con il plug-in Android Gradle 7.4.0 o versioni successive, sono disponibili anche una serie di API di linguaggio Java 11 con la libreria 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 estendono il motore di desugaring anche alle API del linguaggio Java. Puoi includere API di lingua standard disponibili solo nelle release Android recenti (ad esempio java.util.streams) nelle app che supportano versioni precedenti di Android.

Il seguente insieme di API è supportato durante la creazione dell'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
  • Aggiunta di recente a java.util.{Map,Collection,Comparator}
  • Componenti facoltativi (java.util.Optional, java.util.OptionalInt e java.util.OptionalDouble) e alcuni nuovi tipi di classi
  • 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 Gradle per Android 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 API Java 8 e versioni successive disponibili tramite la desugaring e API Java 11 e versioni successive disponibili tramite la desugaring.

Per supportare queste API di linguaggio, il plug-in compila un file DEX distinto che contiene un'implementazione delle API mancanti e lo include nella tua app. Il processo di desugaring riscrive il codice dell'app in modo da utilizzare questa libreria in fase di esecuzione. Il codice sorgente compilato nel file DEX separato è disponibile nel repository GitHub desugar_jdk_libs.

Per attivare il supporto di queste API di lingua 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")
}

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

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

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

  • Vuoi eseguire lint sul modulo della libreria in isolamento. Questo è utile per aiutare il lint a riconoscere gli utilizzi validi delle API di linguaggio ed evitare di segnalare falsi avvisi.

Tieni inoltre presente che l'ottimizzazione dell'API può essere combinata con lo shrinking, ma solo se utilizzi lo shrinker R8.

Versioni

La tabella seguente mostra le versioni della libreria API Java 8 e la versione minima del plug-in Gradle per Android che supporta ciascuna 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 informazioni dettagliate sulle versioni della libreria API Java 8 e successive, consulta il file CHANGELOG.md nel repository GitHub desugar_jdk_libs.