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

时间:2013-04-17 09:30:48

标签: android ant quickblox antbuilder

我开发的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

由于我没有任何这些库,我寻找方法限制错误的解决方案。我在Android Developers中找到了一个受欢迎的博客文章,推荐使用源代码部门。 (我正在谈论的博客文章可以在这里找到: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>

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

2 个答案:

答案 0 :(得分:6)

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

ProGuard仅在Eclipse中执行导出时运行,而不是在执行Run As时运行 - &gt; Android应用程序。这意味着它无助于避免调试版本的限制,除非您使用自定义构建过程。 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"'

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

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中的方法数量(可在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

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

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

答案 1 :(得分:0)

ProGuard是一个源代码缩小工具,在打包应用程序时会删除所有未使用/重复的类。因此,即使您正在使用所有这些外部JAR,您也不会100%使用其中的所有类,并且其中许多JAR可能在其中具有相同的类(例如Log4J等)。

Proguard is built into dex。但它默认情况下不会被激活,你必须在发布模式下运行ant,你可能还需要在project.properties中注释掉一行。

最有可能的是,ProGuard最终可能删除应用程序中使用的某些类。如果在ProGuard编译时遇到class X not found之类的错误,请在proguard.cfg中配置需要该类的ProGuard:

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

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