Java 8 언어 기능 및 API 사용

Android Gradle 플러그인 3.0.0 이상에서는 모든 Java 7 언어 기능과 플랫폼 버전에 따라 다른 Java 8 언어 기능의 일부를 지원합니다. Android Gradle 플러그인 4.0.0 이상을 사용하여 앱을 빌드할 때 앱의 최소 API 수준 없이도 일부 Java 8 언어 API를 사용할 수 있습니다.

이 페이지에서는 사용할 수 있는 Java 8 언어 기능, 이러한 기능을 사용할 프로젝트를 올바르게 구성하는 방법, 발생할 수 있는 알려진 문제에 관해 설명합니다. Java 8 언어 기능에 관한 개요는 다음 동영상을 참고하세요.

Android Gradle 플러그인은 특정 Java 8 언어 기능과 이러한 기능을 사용하는 서드 파티 라이브러리를 사용하기 위한 내장 지원 기능을 제공합니다. 기본 도구 모음은 클래스 파일을 DEX 코드에 D8/R8 컴파일하는 과정의 일환으로, desugar라는 바이트 코드 변환을 실행하여 새로운 언어 기능을 구현합니다(그림 1 참고).

`desugar` 바이트 코드 변환을 사용하는 Java 8 언어 기능 지원
그림 1. desugar 바이트 코드 변환을 사용하는 Java 8 언어 기능 지원

Java 8 언어 기능 지원(Android Gradle 플러그인 3.0.0 이상)

지원되는 Java 8 언어 기능을 사용하려면 다음 단계를 따르세요.

  1. 3.0.0 이상으로 Android Gradle 플러그인을 업데이트합니다.
  2. 소스 코드에서 또는 종속 항목을 통해 Java 8 언어 기능을 사용하는 각 모듈의 경우 다음과 같이 모듈의 build.gradle 또는 build.gradle.kts 파일을 업데이트합니다.

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

Android Gradle 플러그인 3.0.0 이상을 사용하여 앱을 빌드할 때 플러그인은 일부 Java 8 언어 기능을 지원하지 않습니다. 다음 언어 기능을 모든 API 수준에서 사용할 수 있습니다.

Java 8 언어 기능 참고
람다 표현식 Android는 람다 표현식의 직렬화를 지원하지 않습니다.
메서드 참조  
형식 주석 형식 주석 정보는 런타임이 아닌 컴파일 시간에만 확인할 수 있습니다. 이 플랫폼은 API 수준 24 이하에서 TYPE을 지원하지만 ElementType.TYPE_USE 또는 ElementType.TYPE_PARAMETER를 지원하지는 않습니다.
기본 및 정적 인터페이스 메서드  
주석 반복  

이러한 Java 8 언어 기능 외에도 Android Gradle 플러그인 버전 3.0.0 이상에서는 try-with-resources 지원을 모든 Android API 수준으로 확장합니다.

Desugar는 MethodHandle.invoke 또는 MethodHandle.invokeExact를 지원하지 않습니다. 소스 코드나 모듈 종속 항목 중 하나에서 이러한 메서드 중 하나를 사용하는 경우 minSdkVersion 26 이상을 지정해야 합니다. 그러지 않으면 다음 오류가 발생합니다.

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

경우에 따라 invoke 또는 invokeExact 메서드가 라이브러리 종속 항목에 포함되어 있을 때도 모듈에서 이러한 메서드를 사용하지 않을 수 있습니다. minSdkVersion 25 이하 버전에서 해당 라이브러리를 계속 사용하려면 코드 축소를 활성화하여 사용되지 않는 메서드를 제거하세요. 그래도 효과가 없으면 지원되지 않는 메서드를 사용하지 않는 다른 라이브러리를 사용해 봅니다.

Java 8+ 언어는 Android Gradle 플러그인 3.0.0 이상에서 디슈가링 기능을 제공하지만 이전 Android 출시에서 사용하도록 추가 클래스 및 API(예: java.util.stream.*)를 제공하지는 않습니다. 부분 Java API 디슈가링은 Android Gradle 플러그인 4.0.0 이상에서 지원됩니다(다음 섹션 참고).

Java 8+ API 디슈가링 지원(Android Gradle 플러그인 4.0.0 이상)

Android Gradle 플러그인 4.0.0 이상을 사용하여 앱을 빌드하고 있다면 이 플러그인은 앱의 최소 API 수준 없이도 다양한 Java 8 언어 API를 사용할 수 있도록 지원을 확대합니다. Android Gradle 플러그인 7.4.0 이상을 사용하면 디슈가링된 라이브러리 2.0.0 이상에서 여러 Java 11 언어 API를 사용할 수 있습니다.

플러그인 4.0.0 이상에서 Java 언어 API도 디슈가링하도록 디슈가링 엔진을 확장하기 때문에 이전 플랫폼 버전을 위한 이 같은 추가 지원이 가능합니다. 최신 Android 출시에서만 사용할 수 있었던 표준 언어 API(예: java.util.streams)를 이전 Android 버전을 지원하는 앱에 포함할 수 있습니다.

Android Gradle 플러그인 4.0.0 이상을 사용하여 앱을 빌드할 경우 다음 API가 지원됩니다.

  • 순차적 스트림(java.util.stream)
  • java.time의 하위 집합
  • java.util.function
  • 최근 java.util.{Map,Collection,Comparator}에 추가된 사항
  • 선택사항 (java.util.Optional, java.util.OptionalInt, java.util.OptionalDouble) 및 일부 새 클래스
  • 일부 java.util.concurrent.atomic에 추가된 사항(AtomicInteger, AtomicLong, AtomicReference의 새 메서드)
  • ConcurrentHashMap(Android 5.0 버그 수정 포함)

Android Gradle 플러그인 7.4.0 이상에서는 java.nio.file 패키지의 하위 집합과 같은 추가 Java 11 API가 지원됩니다.

지원되는 API의 전체 목록은 디슈가링을 통해 사용할 수 있는 Java 8+ API디슈가링을 통해 사용할 수 있는 Java 11+ API를 참고하세요.

이러한 언어 API를 지원하기 위해 플러그인에서는 누락된 API의 구현을 포함하는 별도의 DEX 파일을 컴파일하고 이를 앱에 포함합니다. 디슈가링 프로세스를 사용하면 앱 코드를 다시 작성하여 런타임에 이 라이브러리를 대신 사용할 수 있습니다.

모든 Android 플랫폼 버전에서 이러한 언어 API를 지원하려면 다음 단계를 따르세요.

  1. 4.0.0 이상으로 Android Gradle 플러그인을 업데이트합니다.
  2. 앱 모듈build.gradle 또는 build.gradle.kts 파일에 다음을 포함합니다.

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

다음의 경우 라이브러리 모듈의 build.gradle 또는 build.gradle.kts 파일에 위 코드 스니펫을 포함해야 할 수 있습니다.

  • 라이브러리 모듈의 계측 테스트가 이러한 언어 API를 직접 또는 라이브러리 모듈이나 모듈의 종속 항목을 통해 사용하는 경우. 이는 누락된 API를 계측 테스트 APK에 제공하기 위함입니다.

  • 라이브러리 모듈에서 린트를 독립적으로 실행하려는 경우. 이렇게 하면 린트에서 언어 API의 올바른 사용을 인식하여 거짓 경고 보고를 방지하도록 할 수 있습니다.

또한 API 디슈가링은 축소와 결합할 수 있지만 R8 축소기를 사용할 때만 가능합니다.

버전

다음 표에는 Java 8+ API 라이브러리의 버전과 각 버전을 지원하는 최소 Android Gradle 플러그인 버전이 나와 있습니다.

버전 최소 Android Gradle 플러그인 버전
1.1.9 4.0.0
1.2.3 7.3.0
2.0.3 7.4.0-alpha10

Java 8+ API 라이브러리 버전에 관한 자세한 내용은 desugar_jdk_libs GitHub 저장소의 CHANGELOG.md 파일을 참고하세요.