アプリ申請時のコンパイルエラーを回避する方法
65,000個に近いメソッドを参照するアプリをAmazonアプリストアに申請すると、Dalvik Executable形式のバイトコードファイルにおける制限により、コンパイルエラーが発生します。
- 65,000個を超えるメソッドの参照に起因するエラーの発生
- Amazonのラッパーによるメソッドの追加
- メソッド参照数の取得
- メソッド参照数の削減
- AndroidXライブラリの難読化の回避
- 関連リソース
65,000個を超えるメソッドの参照に起因するエラーの発生
65,000個に近いメソッドを参照するアプリをAmazonアプリストアに申請すると、次のエラーメッセージがEメールで届くか、[App status] タブに表示されることがあります。
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
このエラーの原因は、Dalvikバイトコード(DEXファイル)で参照するメソッド数の上限が65,535になっていることにあります。詳細については、Androidドキュメントの64Kを超えるメソッドを使用するアプリ向けにMultidexを有効化するを参照してください。
Amazonのラッパーによるメソッドの追加
Amazonアプリストアではすべてのアプリをコードでラッピングして、各種レポート、分析、DRM、アプリのアップデートなどを開発者が実行できるようにしています。このラッパーにより、Amazonライブラリの参照先メソッドが1,627個追加され、アクティビティごとにメソッド数が9個ずつ増えます。このように参照先メソッドが追加されるため、アプリの参照先メソッドが65,000個近くに達した場合、メソッドの制限を超える可能性があります。
こうした制限は以前からありましたが、Android 5.0(Lollipop)のリリース以降、メソッド参照の上限を超えるケースが頻繁に発生するようになりました。Android 5.0に追加された機能により、アプリが参照するメソッドの数が増えやすくなっためです。
この制限を回避するには、アプリでのメソッドの参照数を調べ、減らすことを検討してください。
メソッド参照数の取得
アプリが参照するメソッドの数、およびメソッドを参照するアプリの機能に関する情報を取得するには、GitHubにあるdex-method-countsツール(https://github.com/mihaip/dex-method-counts)を使用できます。
メソッド参照数の削減
メソッドの参照数を減らすには、余分なライブラリとメソッドをできるだけ削除します。または、ProGuardを-dontoptimize –dontobfuscate
オプションを指定して使用すると、使用していないメソッドをビルド時にDEXファイルから削除できます。
上記の方法でもメソッド数を減らしきれない場合は、Multidexライブラリを使用してclasses.dex
を複数のDEXファイルに分割します。
Multidexライブラリは、Android Gradleプラグインで使用できます。詳細については、64Kを超えるメソッドを使用するアプリ向けにMultidexを有効化するを参照してください。
multidex(複数のDEXファイルに分割する手法)アプローチでは、以下の点に注意してください。
- 必ず、Android開発環境でGradleを使用してください。
- Multidexを使っても十分な数のメソッドを削除できない場合は、いくつか追加で手順を実行する必要があります(次のセクションで概要を説明しています)。
上記で説明したdex-method-countsツールを使用すると、作成されるclasses.dex
ファイルのメソッド数を確認できます。
Multidexライブラリの使用
Android 5.0 Lollipopでは、サポートライブラリ(android-support-multidex.jar
)が、Android SDKバージョン21.1.xおよびAndroid Support Library 21.0.3に導入されました。このサポートライブラリは、\android-sdk\extras\android\support\multidex\library\libs
にあります。ライブラリには、MultiDex
とMultiDexApplication
の2つの新しいクラスが含まれており、Multidexの読み込みプロセスを簡略化できます。
Android 5.0はもともとセカンダリDEXファイルをサポートしているため、Android 5.0のみを対象とするアプリの場合、このライブラリは不要です。ただし、Android 5.0より前のバージョンでは、.dex
ファイルがAPKアーカイブからクラスローダーに追加されます。ライブラリを使用するとアーカイブがアプリのプライマリDEXファイルの一部になり、追加されたDEXファイルへのアクセスを管理できます。そのため、Android 5.0より前のリリースをターゲットにしたアプリでは、すべてこのライブラリを使用する必要があります。
このソリューションをAndroid 5.0よりも前のアプリに実装するには、次の操作を行います。
- Androidビルドツールを最新バージョンに更新していることを確認します。21.1.x以降のバージョンが必要です。
- プロジェクトに
android-support-multidex.jar
ライブラリを追加します。このライブラリは、\android-sdk\extras\android\support\multidex\library\libs
にあります。 -
以下の例に示すように、
multiDexEnabled true
とMultidexの依存関係をbuild.gradle
ファイルのbuildConfig
に追加します。android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { ... minSdkVersion 14 targetSdkVersion 21 ... // Multidexサポートを有効にします。 multiDexEnabled true } ... } dependencies { compile 'com.android.support:multidex:1.0.0' }
-
以下のコードに示すように、
android.app.Application
クラスを上書きするか、MultiDexApplication
クラスをAndroidManifest.xml
ファイルで宣言します。<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="android.support.multidex.MultiDexApplication"> ... </application>
-
プロジェクトに追加のライブラリがある場合は、必ずライブラリに対する事前のDEX化を無効にします。
--multi-dex
オプションは、事前にDEX化されたライブラリと互換性がありません。以下のコードを
app/build.gradle
ファイルに追加すると、事前のDEX化を無効にできます。android { // ... dexOptions { preDexLibraries = false } }
注: これまでは、dexOptions
を使用して、additionalParameters = ["--set-max-idx-number=55000"]
のようにプロパティを追加することで、単一のDEXファイルごとにメソッドの最大数を設定することができました。新しいAndroidコンパイラD8とAndroid Studio 3.1.2では、–set-max-idx-number
が無効になります。そのため、このプロパティを含めると、アプリの申請時にエラーが発生します。 -
multidex化アプリがAmazonアプリストアと申請プロセスに対して最適化されるようビルド手順を設定します。次の2つのオプションがあります。
-
main-dex-list
ファイルを手動で作成します。app/build.gradleファイルで、以下を追加します。afterEvaluate { tasks.matching { it.name.startsWith('dex') }.each { dx -> if (dx.additionalParameters == null) { dx.additionalParameters = [] } dx.additionalParameters += '--multi-dex' dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString() } }
このコードでは、次の2つのパラメーターを使用します。
--multi-dex
— ビルドプロセスでの分割メカニズムを有効にします。--main-dex-list
— メインのDEXファイルで添付する必要があるクラスのリストを含むファイルです。
multidex化アプリが申請を経て、適切にAmazonアプリストアで公開されるようにするには、
--main-dex-list
パラメーターを使用して、以下をメインの.dex
ファイルで指定する必要があります。- カスタムアプリ
- アクティビティ
- サービス
- レシーバー
- プロバイダー
- インストルメンテーション
- 注釈
-
Studio 0.9.0とGradle 0.14.2を使用している場合は、
multi-dex
およびmulti-dex-list
パラメーターを無視し、ビルドツールで自動的にdx.additionalParameters
パラメーターを60,000
に制限します。この方法はほとんどのアプリで有効ですが、アプリで非常に多くのクラスを使用している場合は、Amazonアプリストアへの申請を通過するために、手動で最大数を60,000未満に設定しなければならない場合があります。
-
AndroidXライブラリの難読化の回避
AndroidXライブラリをmultidex化に使用している場合は、Proguardファイルに次の行を追加して、コードのAndroidXライブラリが難読化されないようにします。
-keep class androidx/multidex.** { *; }
関連リソース
main-dex-list
の生成については、次の情報が役立ちます。
- CreateManifestKeepList.groovy - Gradleによる
main-dex-list
の自動生成に関するソースコードです。 - main-dex-listを自動生成できるツール
Last updated: 2023年10月2日