Używaj funkcji i interfejsów API w języku Java 8

Wtyczka Android Gradle w wersji 3.0.0 lub nowszej obsługuje wszystkie funkcje języka Java 7 oraz podzbiór funkcji języka Java 8, które różnią się w zależności od wersji platformy. Podczas kompilowania aplikacji za pomocą wtyczki Gradle na Androida w wersji 4.0.0 lub nowszej możesz używać niektórych interfejsów API języka Java 8 bez konieczności stosowania minimalnego poziomu interfejsu API w aplikacji.

Na tej stronie opisaliśmy funkcje języka Java 8, których możesz używać, jak prawidłowo skonfigurować projekt, aby z nich korzystać, oraz jakie znane problemy mogą wystąpić. Aby zapoznać się z funkcjami języka Java 8, obejrzyj ten film.

Wtyczka Gradle dla Androida zapewnia wbudowane wsparcie dla niektórych funkcji języka Java 8 i bibliotek innych firm, które z nich korzystają. Domyślne narzędzia implementują nowe funkcje języka, wykonując transformacje kodu bajtowego (nazywane desugar) w ramach kompilacji D8/R8 plików klas na kod DEX, jak pokazano na rysunku 1.

Obsługa funkcji języka Java 8 za pomocą przekształceń kodu bajtowego „desugar”
Rysunek 1. Obsługa funkcji języka Java 8 za pomocą transformacji kodu bajtowego desugar.

Obsługa funkcji języka Java 8 (wtyczka Androida do obsługi Gradle w wersji 3.0.0 lub nowszej)

Aby zacząć korzystać z obsługiwanych funkcji językowych Java 8:

  1. Zaktualizuj wtyczkę Androida do obsługi Gradle do wersji 3.0.0 lub nowszej.
  2. W przypadku każdego modułu, który korzysta z funkcji języka Java 8 (w źródle lub w zależnościach), zaktualizuj plik build.gradle lub build.gradle.kts modułu w ten sposób:

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

Podczas kompilowania aplikacji za pomocą wtyczki Androida do obsługi Gradle w wersji 3.0.0 lub nowszej ta wtyczka nie obsługuje wszystkich funkcji języka Java 8. Na dowolnym poziomie interfejsu API dostępne są te funkcje językowe:

Funkcja języka Java 8 Uwagi
Wyrażenia lambda Android nie obsługuje serializacji wyrażeń lambda.
Odwołania do metody  
Adnotacje typu Informacje o adnotacji typu są dostępne tylko w czasie kompilacji, a nie w czasie wykonywania. Platforma obsługuje TYPE na poziomie interfejsu API 24 i starszym, ale nie ElementType.TYPE_USE ani ElementType.TYPE_PARAMETER.
Domyślne i statyczne metody interfejsu  
Powtarzające się adnotacje  

Oprócz tych funkcji języka Java 8 wtyczka Gradle dla Androida w wersji 3.0.0 i nowszych rozszerza obsługę funkcji try-with-resources na wszystkich poziomach interfejsu API Androida.

Desugar nie obsługuje MethodHandle.invoke ani MethodHandle.invokeExact. Jeśli Twój kod źródłowy lub jedno z zależności modułu używa jednej z tych metod, musisz podać minSdkVersion 26 lub nowszą. W przeciwnym razie pojawi się ten komunikat o błędzie:

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

W niektórych przypadkach moduł może nie używać metod invoke ani invokeExact, nawet jeśli są one uwzględnione w zależności biblioteki. Aby nadal korzystać z tej biblioteki z minSdkVersion 25 lub niższą wersją, włącz zmniejszanie kodu, aby usunąć nieużywane metody. Jeśli to nie zadziała, użyj innej biblioteki, która nie korzysta z nieobsługiwanych metod.

Desugaring funkcji języka Java 8+ w pliku Android Gradle Plugin 3.0.0 lub nowszym nie powoduje udostępnienia dodatkowych klas i interfejsów API (takich jak java.util.stream.*) do użycia w starszych wersjach Androida. Obsługa częściowego usuwania cukru z interfejsów API w języku Java jest dostępna w Android Gradle w wersji 4.0.0 lub nowszej, zgodnie z opisem w następnej sekcji.

Obsługa decukrowania interfejsu API w Java 8 lub nowszej (Android Gradle Plugin 4.0.0 lub nowszy)

Jeśli kompilujesz aplikację za pomocą wtyczki Android Gradle w wersji 4.0.0 lub nowszej, wtyczka rozszerza obsługę interfejsów API języka Java 8, nie wymagając minimalnego poziomu interfejsu API w aplikacji. W przypadku wtyczki Android Gradle w wersji 7.4.0 lub nowszej dostępne są też interfejsy API języka Java 11 z desugarowaną biblioteką w wersji 2.0.0 lub nowszej.

Dodatkowa obsługa starszych wersji platformy jest możliwa, ponieważ w pluginie 4.0.0 i nowszych rozszerzono mechanizm desugarowania o desugarowanie interfejsów API języka Java. W aplikacjach obsługujących starsze wersje Androida możesz używać interfejsów API standardowego języka, które były dostępne tylko w najnowszych wersjach Androida (np. java.util.streams).

Podczas kompilowania aplikacji za pomocą wtyczki Gradle na Androida w wersji 4.0.0 lub nowszej obsługiwany jest ten zestaw interfejsów API:

  • Sekwencyjne strumienie (java.util.stream)
  • Podzbiór java.time
  • java.util.function
  • Ostatnie dodane do java.util.{Map,Collection,Comparator}
  • Opcjonalne (java.util.Optional, java.util.OptionalIntjava.util.OptionalDouble) oraz niektóre nowe klasy.
  • Niektóre dodatki do java.util.concurrent.atomic (nowe metody w AtomicInteger, AtomicLongAtomicReference)
  • ConcurrentHashMap (z poprawkami błędów dla Androida 5.0)

W pluginie Android Gradle w wersji 7.4.0 lub nowszej obsługiwane są dodatkowe interfejsy API Java 11, np. podzbiór pakietu java.nio.file.

Pełną listę obsługiwanych interfejsów API znajdziesz w interfejsach API Java 8 lub nowszej wersji dostępnych za pomocą desugaringu oraz interfejsów API Java 11 lub nowszej wersji dostępnych za pomocą desugaringu.

Aby obsługiwać te interfejsy językowe, wtyczka kompiluje oddzielny plik DEX, który zawiera implementację brakujących interfejsów API i włącza go w aplikacji. Proces decukrzenia przepisuje kod aplikacji, aby używał tej biblioteki w czasie wykonywania. Kod źródłowy skompilowany w osobnym pliku DEX jest dostępny w repozytorium GitHub desugar_jdk_libs.

Aby włączyć obsługę tych interfejsów API języka w dowolnej wersji platformy Android:

  1. Zaktualizuj wtyczkę Androida do obsługi Gradle do wersji 4.0.0 (lub nowszej).
  2. W pliku build.gradle lub build.gradle.kts modułu aplikacji umieść:

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

Pamiętaj, że poprzedni fragment kodu może być też potrzebny w pliku build.gradle lub build.gradle.kts modułu biblioteki, jeśli:

  • Testy z użyciem modułu biblioteki korzystają z tych interfejsów API języka (bezpośrednio lub za pomocą modułu biblioteki lub jego zależności). Dzięki temu brakujące interfejsy API są udostępniane dla testowego pliku APK z instrumentacją.

  • chcesz uruchomić lint na module biblioteki w osobnym środowisku; Ma to pomóc lintowi rozpoznać prawidłowe użycie interfejsów API języka i uniknąć raportowania fałszywych ostrzeżeń.

Pamiętaj też, że desugaring interfejsu API można łączyć ze skracaniem, ale tylko w przypadku użycia narzędzia R8.

Wersje

Poniższa tabela zawiera wersje biblioteki interfejsu API Java 8 i później oraz minimalną wersję wtyczki Gradle na Androida, która obsługuje każdą z nich:

Wersja Minimalna wersja wtyczki Androida do obsługi Gradle
1.1.9 4.0.0
1.2.3 7.3.0
2.0.3 7.4.0-alpha10

Szczegółowe informacje o wersjach biblioteki interfejsu API Java 8+ znajdziesz w pliku CHANGELOG.md w repozytorium GitHub desugar_jdk_libs.