자바 8 언어 기능 및 API 사용

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

Android Gradle 플러그인 3.0.0 이상은 자바 7 언어 기능을 모두 지원하고, Java 8 언어 기능의 경우 플랫폼 버전에 따라 각각 다르게 부분적으로 지원합니다. Android Gradle 플러그인 4.0.0 이상을 사용하여 앱을 빌드하면 앱의 최소 API 수준 없이도 다양한 자바 8 언어 API를 사용할 수 있습니다.

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

참고: Android용 앱 개발 시 자바 8 언어 기능을 사용하는 것은 선택사항입니다. 프로젝트의 소스 및 대상 호환성 값을 자바 7로 유지할 수는 있지만 JDK 8을 사용하여 컴파일해야 합니다.

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

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

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

지원되는 자바 8 언어 기능을 사용하려면 3.0.0 이상으로 Android 플러그인을 업데이트하세요. 그런 다음 (소스 코드에서 또는 종속 항목을 통해) 자바 8 언어 기능을 사용하는 각 모듈을 대상으로 아래에 나와 있는 것처럼 모듈의 build.gradle 파일을 업데이트하면 됩니다.

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

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

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

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

위에서 설명한 자바 8 언어 기능 외에도, 플러그인 버전 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 이하 버전에서 해당 라이브러리를 계속 사용하려면 코드 축소를 활성화하여 사용되지 않는 메서드를 제거하세요. 그래도 효과가 없으면 지원되지 않는 메서드를 사용하지 않는 다른 라이브러리를 사용해 봅니다.

Android Gradle 플러그인 3.0.0에서 사용 가능한 자바 8+ 언어 기능 디슈가링을 진행해도 추가 클래스와 API(예: java.util.stream.*)를 이전 Android 버전에서 사용할 수는 없습니다. 부분 자바 API 디슈가링을 위한 지원은 Android Gradle 플러그인 4.0.0 이상에서 제공되며, 다음 섹션에 설명되어 있습니다.

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

Android Gradle 플러그인 4.0.0 이상을 사용하여 앱을 빌드하면 이 플러그인은 앱의 최소 API 수준 없이도 다양한 자바 8 언어 API를 사용할 수 있도록 지원을 확대합니다.

플러그인 4.0.0 이상에서 자바 언어 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.OptionalIntjava.util.OptionalDouble)과 위의 API에서 유용하게 사용할 수 있는 몇 가지 새로운 클래스
  • 일부 java.util.concurrent.atomic에 추가된 사항(AtomicInteger, AtomicLong, AtomicReference의 새 메서드)
  • ConcurrentHashMap(Android 5.0 버그 수정 포함)

지원되는 API의 전체 목록을 보려면 디슈가링을 통해 사용할 수 있는 자바 8+ API를 참고하세요.

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

Android 플랫폼의 모든 버전에서 이러한 언어 API의 지원을 사용하려면 4.0.0(또는 그 이상)으로 Android 플러그인을 업데이트하고 앱 모듈build.gradle 파일에 다음을 포함하세요.

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 {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}

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 {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
}

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

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

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

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

버전

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

버전 최소 Android Gradle 플러그인 버전
1.1.5 4.0.0
1.2.0 7.3.0
2.0.0 7.4.0-alpha10
사용되는 Java 8+ API 라이브러리 버전에 관한 자세한 내용은 desugar_jdk_libs GitHub 저장소의 CHANGELOG.md 파일을 참고하세요.