17

複数のライブラリ (特に Facebook、Google マップ v2、Quickblox 用) を必要とする Android アプリを開発しているため、64K の制限を超えるメソッド量のオーバーフローが発生します。

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

私はこれらのライブラリがなければできないので、メソッド制限バグの解決策を探しました。Android Developers から、ソース コード部門が推奨されている人気のブログ エントリを見つけました。(私が話しているブログ エントリは、ここにあります: http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html )。私はこの解決策を試してきましたが、成功しませんでした。

私が今抱えている問題は、最大量のコードがアプリ自体ではなく、必要なライブラリにあるため、アプリにロードする必要があるさまざまな dex ファイルにそれらのライブラリを分散させる必要があることです。Ant に関する私の知識は非常に限られています。知りたいのは、必要な場所に各ライブラリを dex コピーするために build.xml ファイルに何を書くべきかです。

            <!-- Primary dex to include my source code and some libraries. -->
            <copy todir="${out.classes.absolute.dir}.1" >
                <fileset dir="${out.classes.absolute.dir}" >

                ...

                </fileset>
            </copy>


            <!-- Secondary dex to include some other libraries. -->
            <copy todir="${out.classes.absolute.dir}.2" >
                <fileset dir="${out.classes.absolute.dir}" >

                ...  

                </fileset>
            </copy>

どんな助けでも本当に感謝します。よろしくお願いします。

4

2 に答える 2

6

この問題に対する私がこれまでに聞いた最良の答えは、ProGuard を最適化モード (proguard-android-optimize.txt) で-dontobfuscate使用し、未使用のクラスとメソッドを最終的な APK から (難読化せずに) 削除することです。次に、ProGuard mapping.txt を使用して、使用しているライブラリ JAR から未使用のクラスを取り除くことができます (これを行うための優れたツールは知りません)。残念ながら、これを自動的に行う ProGuard の機能はないと思います。

ProGuard は、Run As -> Android Application を実行するときではなく、Eclipse でエクスポートを実行するときにのみ実行されます。これは、カスタム ビルド プロセスを使用しない限り、デバッグ ビルドの制限を回避するのに役立たないことを意味します。ProGuard の作成者は、商用の兄弟であるDexGuardを使用することを提案しています。これは、デバッグ ビルドとリリース ビルドの両方で Eclipse で実行されます。

リリース ビルドでは ProGuard を使用することを強くお勧めします。ProGuard を使用すると、コード サイズが縮小され、パフォーマンスが向上し (コードのインライン化などによって)、ソースも難読化されるからです。デバッグ用の APK とは大きく異なるため、最終的な APK で十分なテストを行ってください。残念ながら、ProGuard だけでは問題を解決するには不十分だったので、回避策として JAR 依存関係の 1 つを削除しました。

次のコマンドを使用して、依存する JAR 内のメソッドの数を確認しました。

dx --dex --output=temp.dex library.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'

最大のライブラリのメソッドの例:

11222 guava-11.0.1.jar    
10452 aws-android-sdk-1.5.0-core.jar    
5761 org.restlet.jar    
5129 protobuf-java-2.4.1.jar    
2499 aws-android-sdk-1.5.0-s3.jar    
2024 ormlite-core-4.41.jar    
1145 gson-2.2.2.jar    
1716 google-http-client-1.11.0-beta.jar    

参考までに、dexdump を使用して APK 内のメソッドの数を確認できます (これは SDKbuild-toolsフォルダーにあります。たとえば、「Android Studio.app/sdk/build-tools/21.0.2/dexdump」)。

dexdump -f MyApp.apk | grep method_ids_size
method_ids_size     : 64295

私たちの場合、YouTube 検索を行うために Guava のみを使用していたため、その依存関係を簡単に取り除き、余裕を持たせることができました。

更新:大きな JAR から未使用のコードを削除する最も簡単な方法は、Proguard ビルドで dex2jar を使用し、JD-GUI を使用して、その最終的な JAR をトリミングしたい特定の入力 JAR と比較することであることがわかりました。次に、Proguard によって削除されることがわかっている最上位のパッケージを削除します。これにより、aws-android-sdk-1.5.0-core.jar から 8000 を超えるメソッドを削除できました。

于 2013-05-27T04:22:42.093 に答える
0

ProGuardはソース コード縮小ツールであり、アプリケーションをパッケージ化するときに未使用または重複するクラスを削除します。したがって、これらすべての外部 JAR を使用している場合でも、それらの内部のすべてのクラスを 100% 使用するわけではなく、これらの JAR の多くは内部に同じクラス (Log4J など) を持つことができます。

Proguard は dex に組み込まれています。ただし、デフォルトではアクティブ化されません。リリース モードで ant を実行する必要があり、project.properties の行をコメント アウトする必要がある場合もあります。

ほとんどの場合、ProGuard は、アプリケーションで使用されている一部のクラスを削除する可能性があります。ProGuard のコンパイル時に のようなエラーが発生する場合は、そのクラスが必要になるclass X not foundように ProGuard を構成します。proguard.cfg

-keep public class <full path to the class that you need>

Android ProGuard のドキュメントをチェックして、proguard を有効にすると APK の (クラスとメソッドの) サイズが小さくなるかどうかを確認してください。

于 2013-05-26T13:29:14.530 に答える