无法使用外部jar中的Ant构建多个Android dex文件

din*_*nri 17 ant android antbuilder quickblox

我正在开发一个需要多个库的Android应用程序(适用于Facebook,Google Maps v2和Quickblox等),导致方法数量溢出超过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
Run Code Online (Sandbox Code Playgroud)

由于我不能没有任何这些库,我寻找方法限制bug的解决方案.我发现了一个来自Android开发者的热门博客文章,推荐使用源代码部门.(我正在谈论的博客条目可以在这里找到:http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html).我一直在尝试这个解决方案但没有成功.

我现在的问题是,最大量的代码不在我的应用程序本身,但在所需的库中,所以我必须在我必须在我的应用程序中加载的不同dex文件中传播这些库.我对Ant的了解非常有限,我想知道的是我应该在build.xml文件中编写什么来使dex复制我想要的每个库:

            <!-- 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>
Run Code Online (Sandbox Code Playgroud)

任何帮助都会得到真正的赞赏.在此先感谢,亲切的问候!

Dan*_*n J 6

到目前为止,我听到这个问题的最佳答案是在优化模式下使用ProGuard(proguard-android-optimize.txt)并使用该-dontobfuscate标志从最终的APK中删除未使用的类和方法(不会混淆它们).然后你可以使用ProGuard mapping.txt来帮助你从你使用的库JAR中删除未使用的类(我不知道这是一个很好的工具).不幸的是,我认为ProGuard中没有自动执行此功能的功能.

ProGuard仅在Eclipse中执行导出时运行,而不是在执行Run As - > Android Application时运行.这意味着它将无助于避免对调试版本的限制,除非您使用自定义构建过程.ProGuard的创建者建议使用其商业兄弟DexGuard,它将在Eclipse上运行调试和发布版本.

强烈建议在发布版本中使用ProGuard,因为它会减少代码大小,提高性能(例如通过内联代码),并且也会混淆源代码.确保你对最终的APK做了足够的测试,因为它与调试版有很大的不同.不幸的是,ProGuard本身并不足以解决我的问题,所以我删除了一个JAR依赖项作为解决方法.

我使用此命令检查了我的依赖JAR中的方法数:

dx --dex --output=temp.dex library.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'
Run Code Online (Sandbox Code Playgroud)

我们最大的图书馆的示例数量:

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    
Run Code Online (Sandbox Code Playgroud)

仅供参考,您可以使用dexdump检查APK中的方法数量(您可以在SDK build-tools文件夹中找到它,例如"Android Studio.app/sdk/build-tools/21.0.2/dexdump"):

dexdump -f MyApp.apk | grep method_ids_size
method_ids_size     : 64295
Run Code Online (Sandbox Code Playgroud)

在我们的例子中,我们只使用Guava进行YouTube搜索,因此很容易消除这种依赖性并为我们提供更多的喘息空间.

更新:我发现从大型JAR中删除未使用代码的最简单方法是在我的Proguard构建中使用dex2jar,然后使用JD-GUI将最终JAR与我想要修剪的特定输入JAR进行比较.然后我删除了我知道被Proguard删除的顶级软件包.这允许我从aws-android-sdk-1.5.0-core.jar中删除> 8000个方法.


Sub*_*has 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>
Run Code Online (Sandbox Code Playgroud)

查看 Android ProGuard 文档,看看启用 proguard 是否会减少 APK 中(类和方法)的大小。