web-dev-qa-db-ja.com

Android:アプリケーションが大きすぎて「dexを実行できません:メソッドIDが[0、0xffff]にありません:65536」と表示されますか?

アプリケーションをBox、Dropbox、Googleドライブと統合しようとしています。これら3つのサービスはすべて、いくつかのサードパーティのjarファイルを必要とします。さらに、私のアプリケーションにはすでにいくつかのサードパーティのjarが必要です。 Eclipseからアプリケーションを実行しようとすると、次のエラーが発生します。

Dexを実行できません:[0、0xffff]にないメソッドID:65536 Dalvik形式への変換に失敗しました:dexを実行できません:[0、0xffff]にないメソッドID:65536

このエラーは、アプリケーションにメソッドが多すぎるために発生しているようです。私はこれらのメソッドの大部分がサードパーティのjarからのものであることをかなり確信しているので、コードを単純化することによってこれを解決しようとすることは非現実的です。これら2つの提案をオンラインで見つけました。

  1. 追加 dex.force.jumbo=trueto project.properties(およびadtバージョン21を使用)。私はこれを行いましたが、それでもエラーが発生します。

  2. ここで説明するように、複数のdexファイルを使用します: http://Android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html 。これが唯一のオプションのようですが、私の場合にどのように適用されるのかわかりません。問題は、ドライブなどのサービスの依存関係が多すぎることです。このソリューションでは、依存関係を参照するときに、語形変化を使用するようにドライブソースを変更する必要がありますか? (これは明らかにオプションではありません)。

  3. プロガードを使用して、未使用のコード/メソッドを縮小削除します。 proguardを使用したアプリケーションのエクスポートは機能し、ドキュメントサービスの統合は、4.0以上のデバイスで期待どおりに機能します。ただし、2.3デバイスでテストすると、classnotfoundエラーがスローされます。

だから、私はこの問題についてのアドバイスを期待しています。オプション2は私のケースの解決策ですか?考慮すべき別の解決策はありますか?

24
ab11

これらの1つ以上を、ダウンロード可能な個別のAPKの形式で、メインアプリへのプラグインとして開発することもできます。そのAPKは、メインアプリが使用するいくつかのコンポーネントを公開します。これらのサービスとの統合の性質がわからないため、それについてより具体的な推奨を行うことはできません。独自のsignatureレベルのカスタム<permission>を使用して、2つのアプリ間の通信を保護します。さらに、おまけとして、サードパーティライブラリを使用して追加の権限の要件を追加する場合、メインのAPKを小さく保ちながら、プラグインAPKでそれらの権限のみが必要になります。

14
CommonsWare

*** NEW ****他のすべての回答は古くなっています。これが新しい修正です

Android 5.0以降

Multi-dexサポートは自動的に含まれます。 ドキュメントから:

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

以下Android 5.0

Android mult-dex support tool to your gradle build: を追加するだけです

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'
}
7
Jason

Dalvik VMは、バイトコード命令セットが16ビット以上を必要とするメソッド番号を参照する方法を持たないため、dexファイルごとに最大65536のメソッドを持つことができます(@danfuzzによって指摘されたように)コメントで)。

複数のdexファイルを使用してこれを修正することは可能ですが、Facebook 別の修正が見つかりました アプリ内で展開して問題を回避できます。

6
Raghav Sood

Vm/LinearAlloc.cを参照してください。このコードを見つけることができます:(Android 2.3.3の下に5MiB、Android 4.0)の後に8MiB)

#define DEFAULT_MAX_LENGTH(5 * 1024 * 1024)

...

LinearAllocHdr * pHdr;

...

pHdr-> mapLength = DEFAULT_MAX_LENGTH;

「Facebookフィックス」がネイティブCポインターを使用してこのメ​​モリを編集していると思います。 IMHO LinearAlloc問題とこのメソッドID問題は異なります。

5
Francesco Jo

最近この問題に直面しました。より詳細な実装についてWebを調査した後、私はそこに他に多くはないことに気づきました:

問題はコードにメソッドが多すぎることではなく、コードと他のライブラリの完全なdexが問題であることに気付きました。したがって、ライブラリに対してコードをコンパイルできても、それらをclasses.dexに含めずに、ライブラリを個別にdexし、実行時にすべてをまとめると、動作するはずです。取り残された唯一の問題は、クラスローダーです。

少しリフレクションといくつかのGroovyコードを使用して、ライブラリとアプリケーションコードを別々のdexファイルにパッケージ化する比較的安定した方法を思いついたと思います。

https://Gist.github.com/nickcaballero/704599

3
Nick Caballero

65kメソッドの制限に達した場合の問題のほとんどは、アプリでのマストドンティックGoogle Playサービスの使用に関連しています。最近、それを使用すると、より細かい設定を取得できます。

このガイド に続いて、必要な部分だけを使用できます。おそらくこれで問題が解決し、いくつかの黒魔術を回避したり、multiDexを使用したりできます。たとえば、アプリでGoogleマップのみが必要な場合(広告、ウォレット、Google Wear、アナリティクスなどを使用していない場合)、依存関係全体を使用することは時間/スペースの無駄になります。あなたはそれをそのように使うことができます:

compile com.google.Android.gms:play-services-base:6.5.87
compile com.google.Android.gms:play-services-maps:6.5.87

「パーツ」の全リストは this link で読むことができます

1
webo80

そのためにDexサポートを有効にする必要があります。したがって、次の手順を実行する必要があります。

  1. AndroidのGradleプラグインv0.14.0はmulti-dexのサポートを追加します。有効にするには、build.gradleで宣言する必要があります:
Android {
   defaultConfig {
      ...
      multiDexEnabled = true
   }
}
  1. アプリのサポートが5.0より大きい場合(つまり、minSdkVersionが20以下の場合)は、アプリケーションClassLoaderに動的にパッチを適用する必要があります。これにより、セカンダリDexeからクラスをロードできるようになります。そのため、このlibを追加できます。
 dependencies {
      ...
      compile 'com.Android.support:multidex:1.0.0'
    }
  1. あなたはこれらのオプションがあることをコードで有効にします。あなたに一番合うものを選んでください

A.マニフェストマニフェストにMultiDexApplicationを追加する

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.example.Android.multidex.App"> <application
Android:name="Android.support.multidex.MultiDexApplication">
</application>
</manifest>

B. MultiDexApplicationによってアプリケーションを拡張する

public class App extends MultiDexApplication { .. }

C.ベースコンテキストをアタッチしてアプリケーションにインストールします。

public class App {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ..
    }

}

詳細については、このリンク MultiDex を参照してください。

0
RATHI

ここ は、特定のフォルダーの各jar(および合計)のメソッド数をカウントするために私が作成したスクリプトです。

メソッドを数えたら、重いライブラリのリファクタリングと削除に集中できます。

0
Tom Susel