Skip to content

Most visited

Recently visited

navigation

64K を超えるメソッドを使用するアプリの設定

Android プラットフォームの継続的な拡張に伴い、Android アプリのサイズも拡大しています。参照されるアプリとライブラリが特定のサイズに到達すると、Android アプリのビルド アーキテクチャの制限に到達したことを示すビルドエラーが発生します。以前のバージョンのビルドシステムでは、このエラーを次のように報告していました。

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

最近のバージョンの Android ビルドシステムでは、異なるエラーが表示されますが、問題の内容は同じです。

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

両方のエラー状態で 65,536 という同じ数字が表示されます。この数字は重要であり、単一の Dalvik Executable(dex)バイトコード ファイル内でコードによって呼び出すことができる参照の総数を表しています。Android アプリをビルドした場合、このエラーに遭遇することがありますが、それはたくさんのコードを書いたという努力の証しです。このドキュメントでは、この制限を越えて、アプリのビルドを続ける方法について説明しています。

注: このドキュメントで提供するガイダンスは、Android デベロッパー ブログに投稿された Dalvik でカスタム クラスを読み込むの内容よりも優先されます。

64K 参照制限について

Android アプリ(APK)ファイルには、実行可能バイトコード ファイルが Dalvik Executable(DEX)の形式で含まれています。このファイルにはアプリの実行に使用されるコンパイル済みのコードがあります。Dalvik Executable の仕様により、単一の DEX ファイル内で参照できるメソッドの総数が 65,536 に制限されます。これらのメソッドには、Android フレームワーク メソッド、ライブラリ メソッド、独自のコードのメソッドが含まれます。コンピュータ サイエンスにおいては、Kilo、K は 1024(または、2^10)を表します。65,536 は 64 X 1024 に等しいため、この制限は「64K 参照制限」と呼ばれます。

この制限を越えるには、Multidex 構成と呼ばれる DEX ファイルを 2 つ以上生成するようにアプリのビルドプロセスを設定する必要があります。

Android 5.0 よりも前の Multidex サポート

Android 5.0(API レベル 21)よりも前のバージョンのプラットフォームでは、アプリコードを実行するために Dalvik ランタイムを使用します。デフォルトでは、Dalvik は APK ごとに単一の classes.dex バイトコード ファイルにアプリを制限します。この制限を回避するために、アプリのプライマリ DEX ファイルの一部になっている Multidex Support Library を使用して、追加の DEX ファイルとこれらのファイルに含まれるコードへのアクセスを管理することができます。

注: minSdkVersion 20 以前を使って Multidex 用にプロジェクトが設定されており、Android 4.4(API レベル 20)以前を実行しているターゲット端末にデプロイしている場合、Android Studio は Instant Run を無効にします。

Android 5.0 以降の Multidex サポート

Android 5.0(API レベル 21)以降では、アプリの APK ファイルから複数の dex ファイルを読み込むことをネイティブにサポートする ART と呼ばれるランタイムを使用します。ART は、アプリのインストール時にプリコンパイルを実行し、classes(..N).dex ファイルをスキャンして、Android 端末で実行するためにこれらのファイルを単一の .oat ファイルにコンパイルします。Android 5.0 ランタイムの詳細については、ART の紹介をご覧ください。

注: Instant Run を使用しているときに、アプリの minSdkVersion が 21 以上に設定されていると、Android Studio はアプリを Multidex 用に自動的に設定します。Instant Run はアプリのデバッグ バージョンのみで機能するため、64K 制限を回避するためには、リリースビルドを Multidex 用に設定する必要があります。

64K 制限の回避

64K 以上のメソッド参照が有効になるようにアプリを設定する前に、アプリのコードや含まれているライブラリで定義されているメソッドなど、アプリのコードによって呼び出される参照の総数を削減する措置を講じる必要があります。以下は、dex 参照制限に到達することを回避するための戦略です。

これらの手法を活用すると、アプリでより多くのメソッド参照を有効にするためにビルド設定を変更する必要がなくなります。また、これらの手順を実行すると、帯域幅のコストが高い市場で特に重要となる APK サイズを削減することができます。

Gradle でアプリを Multidex 用に設定

Android SDK Build Tools 21.1 以降で利用できる Android Plugin for Gradle は、Multidex をビルド設定の一部としてサポートします。Multidex 用にアプリを設定する前に、SDK Manager を使用して、Android SDK Build Tools と Android Support Repository を最新バージョンにアップデートする必要があります。

Multidex 設定を使用するようにアプリ開発プロジェクトをセットアップするには、アプリ開発プロジェクトにいくつかの変更を加える必要があります。特に、次の手順を実行する必要があります。

次のコード スニペットに示すように、モジュールレベルの build.gradle ファイル設定を変更して、サポート ライブラリを含め、Multidex 出力を有効にします。

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

マニフェストで、MultiDexApplication クラスを Multidex Support Library からアプリ要素に追加します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

これらの構成設定がアプリに追加されると、Android ビルドツールは、プライマリ dex(classes.dex)とサポート dex(classes2.dex、classes3.dex)を必要に応じて作成します。その後、ビルドシステムはこれらのファイルを配布用の APK ファイルにパッケージ化します。

注: アプリが Application クラスの拡張を使用している場合、attachBaseContext() メソッドをオーバーライドし、MultiDex.install(this) を呼び出して Multidex を有効にすることができます。詳細については、MultiDexApplication のリファレンス ドキュメントをご覧ください。

Multidex Support Library の制限事項

Multidex Support Library には、注意すべき既知の制限事項がいくつかあり、アプリのビルド設定に Multidex Support Library を組み込む場合はそれらをテストする必要があります。

Multidex 開発ビルドの最適化

Multidex 設定では、プライマリ DEX ファイル、セカンダリ DEX ファイルに、それぞれどのクラスを含めるべきかビルドシステムで複雑な判断をする必要があるため、ビルド処理に非常に長い時間を要します。つまり、開発プロセスの一環として実施される Multidex を使ったルーチンビルドは、一般的により時間がかかるため、開発プロセスを遅延させる可能性があります。

Multidex 出力の長いビルド時間を短縮するには、Android Plug-in for Gradle の productFlavors(開発フレーバーと実稼働フレーバー)を使用して、ビルド出力に 2 つのバリエーションを作成する必要があります。

開発フレーバー向けに、最小 SDK バージョンを 21 に設定します。この設定では、ART 対応形式を使用して Multidex 出力をより速く生成します。リリース フレーバー向けには、実際の最小サポート レベルに一致する最小 SDK バージョンを設定します。この設定では、より多くの端末と互換性がある Multidex APK が生成されますが、ビルドに時間がかかります。

次のビルド設定のサンプルは、Gradle のビルドファイルでこれらのフレーバーをセットアップする方法を示しています。

android {
    productFlavors {
        // Define separate dev and prod product flavors.
        dev {
            // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
            // to pre-dex each module and produce an APK that can be tested on
            // Android Lollipop without time consuming dex merging processes.
            minSdkVersion 21
        }
        prod {
            // The actual minSdkVersion for the application.
            minSdkVersion 14
        }
    }
          ...
    buildTypes {
        release {
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

この設定変更が完了すると、アプリの devDebug バリアントを使用することができます。このバリアントは、dev productFlavor と debug buildType の属性の組み合わせです。このターゲットを使用すると、ProGuard が無効で Multidex が有効になっている、minSdkVersion が Android API レベル 21 に設定されたデバッグアプリが作成されます。これらの設定では、Android Plugin for Gradle が次の処理を実行します。

  1. アプリの各モジュール(依存関係を含む)を個別の dex ファイルとしてビルドします。一般に、これは pre-dex と呼ばれます。
  2. 各 dex ファアイルを変更せずに APK に含めます。
  3. 最も重要なのは、モジュール dex ファイルは統合されないため、プライマリ dex ファイルのコンテンツを決定するための長い計算を回避できるということです。

これらの設定では、変更されたモジュールの dex ファイルのみが再計算されて、APK ファイルに再パッケージ化されるため、高速の増分ビルドが実現します。これらのビルドから得られる APK は、Android 5.0 端末でのテストのみに使用できます。ただし、この設定をフレーバーとして実装すると、リリースに適切な最小 SDK レベルと ProGuard 設定で通常のビルドを実行する機能を保持することができます。

prodDebug バリアントなど、その他のバリアントをビルドすることもできます。このビルドはより長時間かかりますが、開発以外のテストに使用することができます。示された設定の中で、prodRelease バリアントが最終テストおよびリリースのバージョンになります。コマンドラインから Gradle タスクを実行している場合、DevDebug を最後に付加して標準のコマンド(./gradlew installDevDebug など)を使用することができます。Gradle タスクでフレーバーを使用する方法の詳細については、Gradle プラグイン ユーザーガイドをご覧ください。

ヒント: 各フレーバーに対してカスタム マニフェストまたはカスタム アプリ クラスを提供すると、サポート ライブラリの MultiDexApplication クラスを使用したり、バリアントに必要な MultiDex.install() のみを呼び出したりすることができます。

Android Studio でのビルド バリアントの使用

ビルド バリアントは、Multidex を使用する際のビルドプロセスの管理に役立ちます。Android Studio では、ユーザー インターフェースでこれらのビルド バリアントを選択することができます。

Android Studio でアプリの "devDebug" バリアントをビルドするには、次の手順を実行します。

  1. 左のサイドバーから [Build Variants] ウィンドウを開きます。このオプションは [Favorites] の横にあります。
  2. 図 1 に示すように、ビルド バリアントの名前をクリックして、別のバリアントを選択します。

図 1. ビルド バリアントが表示された Android Studio の左パネルのスクリーンショット。

注: このウィンドウを開くオプションは、[Tools] > [Android] > [Sync Project with Gradle Files] コマンドを使用して、Android Studio と Gradle ビルドファイルを正常に同期した後にのみ利用可能になります。

Multidex アプリのテスト

Multidex アプリ用の計測テストを記述するとき、追加の設定は不要です。MultiDexApplication を使用しているか、カスタム Application オブジェクトで attachBaseContext() メソッドをオーバーライドし、MultiDex.install(this) を呼び出して Multidex を有効にしている限り、AndroidJUnitRunner はそのままの状態で Multidex をサポートします。

または、AndroidJUnitRunner で onCreate() メソッドをオーバーライドすることができます。

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ...
}

注: テスト APK を作成する目的での Multidex の使用は、現在サポートされていません。

This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.