Android Gradle プラグイン 3.0.0 以降では、すべての Java 7 言語機能と、プラットフォームのバージョンごとに異なる Java 8 言語機能のサブセットがサポートされます。Android Gradle プラグイン 4.0.0 以上を使用してアプリをビルドする場合は、アプリの最小 API レベルを必要とすることなく、多数の Java 8 言語 API を使用できます。
このページでは、利用可能な Java 8 言語機能、それを利用するためのプロジェクトの適切な設定方法、そして遭遇する可能性がある既知の問題について説明します。概要については、次の動画もご覧ください。
注: Android 向けのアプリを開発する際、必ずしも Java 8 言語機能を使用する必要はありません。プロジェクトのソースおよびターゲットの互換性の値の設定を Java 7 のままにすることもできます。ただし、その場合もコンパイルには JDK 8 を使用する必要があります。
Android Gradle プラグインは、特定の Java 8 言語機能と、それを使用するサードパーティ ライブラリを利用するための組み込みのサポートを提供します。図 1 に示すように、デフォルトのツールチェーンは、クラスファイルを DEX コードに変換する D8 / R8 コンパイルの一環として desugar
と呼ばれるバイトコード変換を実行することにより、新しい言語機能を実装します。
図 1: desugar
バイトコード変換を使用した Java 8 言語機能のサポート
Java 8 言語機能のサポート(Android Gradle プラグイン 3.0.0+)
サポートされている Java 8 言語機能の使用を開始するには、3.0.0
(またはそれ以上)に Android プラグインをアップデートします。その後、(ソースコード内で、または依存関係を通して)Java 8 言語機能を使用するモジュールごとに、次のようにモジュールの build.gradle
ファイルを更新します。
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 はサポートしません。 |
デフォルトおよび静的インターフェース メソッド | |
繰り返しアノテーション |
プラグイン バージョン 3.0.0 以降では、上記の Java 8 言語機能に加えて、try
-with-resources のサポートがすべての Android API レベルに拡張されています。
desugar は、現在 MethodHandle.invoke
または MethodHandle.invokeExact
をサポートしていません。ソースコードまたはいずれか 1 つのモジュール依存関係でこれらのメソッドのいずれかが使用されている場合は、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 以降で利用可能な Java 8+ 言語機能の desugar により、追加のクラスと API(java.util.stream.*
など)を古い Android リリースで利用可能にすることはできません。Android Gradle プラグイン 4.0.0 以上では、Java API の desugar の部分的なサポートを利用できます。これについては次のセクションで説明します。
Java 8+ API の desugar のサポート(Android Gradle プラグイン 4.0.0+)
Android Gradle プラグイン 4.0.0 以上を使用してアプリをビルドする場合、このプラグインは、アプリの最小 API レベルを必要とすることなく、多数の Java 8 言語 API のサポートを拡張します。
4.0.0 以上のプラグインは desugar エンジンを拡張して Java 言語 API も desugar するため、古いプラットフォーム バージョンの追加サポートが可能です。これにより、最近の 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}
の最新の追加 API- オプション(
java.util.Optional
、java.util.OptionalInt
、java.util.OptionalDouble
)および上記の API で役立つその他の新しいクラス java.util.concurrent.atomic
の追加 API(AtomicInteger
、AtomicLong
、AtomicReference
の新しいメソッド)ConcurrentHashMap
(Android 5.0 のバグを修正)
サポートされている API の完全なリストについては、desugar で利用可能な Java 8+ API をご覧ください。
これらの言語 API をサポートするため、プラグインは不足している API の実装を含む別個の DEX ファイルをコンパイルしてアプリに追加します。desugar プロセスはアプリのコードを書き換えて、実行時にこのライブラリが代わりに使用されるようにします。
Android プラットフォームのすべてのバージョンでこれらの言語 API のサポートを有効にするには、4.0.0
(またはそれ以上)に Android プラグインをアップデートして、アプリ モジュールの build.gradle
ファイルに以下の行を含めます。
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.0.9'
}
また、次の場合は、ライブラリ モジュールの build.gradle
ファイルにも上記のコード スニペットを含める必要があります。
ライブラリ モジュールのインストルメンテーション テストで、このような言語 API を直接使用するか、ライブラリ モジュールまたはその依存関係を通じて使用する場合。これは、インストルメンテーション テスト APK を実行するために不足している API を提供する場合に行います。
ライブラリ モジュールの lint を単独で実行する場合。これは、lint が言語 API が有効に使用されていることを認識し、誤った警告を報告しないようにするために行います。