アプリ申請時のコンパイルエラーを回避する


アプリ申請時のコンパイルエラーを回避する

65,000個に近いメソッドを参照するアプリをAmazonアプリストアに申請すると、Dalvik Executable形式のバイトコードファイルにおける制限により、コンパイルエラーが発生します。

65,000個を超えるメソッドの参照によるエラーの発生

65,000個に近いメソッドを参照するアプリをAmazonアプリストアに申請すると、次のエラーメッセージがEメールで届くか、[審査状況] タブに表示されることがあります。

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になっていることにあります。詳細については、64Kを超えるメソッドを使用するアプリの設定というAndroidドキュメントを参照してください。

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ファイルから削除できます。

上記の方法でもメソッド数を減らしきれない場合は、multi-dexを使ってclasses.dexを複数のDEXファイルに分割します。

multidexライブラリは、Android Gradleプラグインで使用できます。詳細については、64Kを超えるメソッドを使用するアプリの設定を参照してください。

multidexアプローチでは、以下の点に注意してください。

  • 必ず、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にあります。ライブラリには、MultiDexMultiDexApplicationの2つの新しいクラスが含まれており、Multidexの読み込みプロセスを簡略化できます。

Android 5.0はもともとセカンダリDEXファイルをサポートしているため、Android 5.0のみを対象とするアプリの場合、このライブラリは不要です。ただし、Android 5.0より前のバージョンでは、.dexファイルがAPKアーカイブからクラスローダーに追加されます。ライブラリを使用するとアーカイブがアプリのプライマリDEXファイルの一部になり、追加されたDEXファイルへのアクセスを管理できます。そのため、Android 5.0より前のリリースでは、すべてこのライブラリを使用する必要があります。

このソリューションをAndroid 5.0よりも前のアプリに実装するには、次の操作を行います。

  1. Androidビルドツールを最新バージョンに更新していることを確認します。21.1.x以降のバージョンが必要です。
  2. プロジェクトにandroid-support-multidex.jarライブラリを追加します。このライブラリは、\android-sdk\extras\android\support\multidex\library\libsにあります。
  3. 以下の例に示すように、multiDexEnabled trueMultidex dependencybuild.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'
    } 
    
  4. 以下のコードに示すように、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>
    
  5. プロジェクトに追加のライブラリがある場合は、必ずライブラリに対する事前のdex化を無効にします。--multi-dexオプションは、事前にdex化されたライブラリと互換性がありません。 

    以下のコードをapp/build.gradleファイルに追加すると、事前のdex化を無効にできます。

    android {
    //  ...
        dexOptions {
            preDexLibraries = false
        }
    }
    
  6. multidexアプリがAmazonアプリストアと申請プロセスに対して最適化されるようビルド手順を設定します。次の2つのオプションがあります。

    1. 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 fileで指定する必要があります。

      • カスタムアプリ
      • アクティビティ
      • サービス
      • レシーバー
      • プロバイダー
      • インストルメンテーション
      • 注釈
    2. Studio 0.9.0とGradle 0.14.2を使用している場合は、multi-dexおよびmulti-dex-listパラメーターを無視し、ビルドツールで自動的にdx.additionalParametersパラメーターを60,000に制限します。この方法はほとんどのアプリで有効ですが、アプリで非常に多くのクラスを使用している場合は、Amazonアプリストアへの申請を通過するために、手動で最大数を60,000未満に設定しなければならない場合があります。

そのほかのリソース

main-dex-listの生成については、次の情報が役立ちます。