项目开发到一定程度遇到了dex超过65536的问题,也就是方法数量超过65536个了,编译不过去,生成不了apk文件,百度了很多文章关于这bug的解决办法,按照步骤实现了都没有效果,不知道怎么解决,有没有在eclipse解决超过65535的问题的大神?请求支援。
以下是我参考的文章:
1、
http://www.lephones.net/2014/11/27/multi-dex-app/
2、
http://blog.youkuaiyun.com/calvin_zhou/article/details/50554184
3、
http://m.blog.youkuaiyun.com/article/details?id=51385240
4、
http://transcoder.baidu.com/from=844b/bd_page_type=1/ssid=0/uid=0/pu=usm%400%2Csz%401320_2001%2Cta%40iphone_1_9.3_3_601/baiduid=A6AF733EDAC649263B154A1E0D516E3E/w=0_10_eclipse+65536/t=iphone/l=3/tcref=www_iphone&lid=4206176381798708912&order=2&fm=alop&tj=www_normal_2_0_10_title&vit=osres&m=8&srd=1&cltj=cloud_title&asres=1&title=eclipse%E4%B8%8B%E4%BD%BF%E7%94%A8MultiDex%E8%A7%A3%E5%86%B365536%E9%99%90%E5%88%B6&dict=30&sec=14742&di=2b6eb361973edbd7&bdenc=1&tch=124.433.29.300.1.261&tch=124.84.77.295.2.648&nsrc=IlPT2AEptyoA_yixCFOxXnANedT62v3IEQGG_yFZ0z3xokmyxP4kHREsRDb6NnTLJ5DhxWeCvB9FuXCh2m9skNYWgK&eqid=3a5f57224bbff6001000000157bfe5a6&wd=&clk_info=%7B%22srcid%22%3A%22www_normal%22%2C%22tplname%22%3A%22www_normal%22%2C%22t%22%3A1472194042805%2C%22xpath%22%3A%22div-a-h3%22%7D
但是跟着步骤解决在dos命令窗口还是出现了问题,分包不成功。有没有亲手操作过的可以推荐篇文章或者赐教步骤么?
后面经过大神的不吝赐教,总结以下步骤:
eclipse下android项目解决方法数超过65536方案
java.lang.IllegalArgumentException: method ID not in [0,0xffff]: 65536, 应用中的Dex 文件方法数超过了最大值65536的上限,简单来说,应用爆棚了.
那么让我们看一下为什么会引起这种错误:
在Android系统中,一个App的所有代码都在一个Dex文件里面。Dex是一个类似Jar的存储了许多Java编译字节码的归档文件。因为Android系统使用Dalvik虚拟机,所以需要把使用Java Compiler编译之后的class文件转换成Dalvik能够执行的class文件。这里需要强调的是,Dex和Jar一样是一个归档文件,里面仍然是Java代码对应的字节码文件。当Android系统启动一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt。DexOpt的执行过程是在第一次加载Dex文件的时候执行的。这个过程会生成一个ODEX文件,即Optimised Dex。执行ODex的效率会比直接执行Dex文件的效率要高很多。但是在早期的Android系统中,DexOpt有一个问题,也就是这篇文章想要说明并解决的问题。DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面。但是这个链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个。当一个项目足够大的时候,显然这个方法数的上限是不够的。尽管在新版本的Android系统中,DexOpt修复了这个问题,但是我们仍然需要对低版本的Android系统做兼容.
由于之前一直是在eclipse上开发的Android项目,所以优先考虑通过动态加载dex的方式解决该问题,而没有采用将项目迁移到AndroidStudio上的方案。
该方案的本质是将可以分包的jar打包为一个apk文件,放在assets文件夹下,在应用初始化时加载此apk文件
下面讲一下具体的操作步骤:
1、将可以分到第二个包的jar文件利用ant合并为一个jar包,如libs.jar。对ant不熟悉的同学也可以采用手动方式合并jar文件,将要合并的jar文件解压到同一目录下,然后将该目录压缩成libs.zip,再重命名为libs.jar
2、使用Android SDK提供的dx工具将libs.jar转换为dex文件,命名为classes.dex。
dx工具可以在Android SDK下找到,如\SDK\build-tools\23.0.1\dx.bat
打开命令行工具,进入到dx.bat所在的目录下,执行命令 如:dx --dex --output=D:\test\classes.dex D:\test\libs.jar
D:\test\classes.dex为打包生成的dex文件的目标路径,D:\test\libs.jar为jar文件的路径
3、将上一步打包生成的classes.dex添加为压缩文件libs.zip, 然后重命名为libs.apk
4、将libs.apk放入项目的assets文件夹下
5.将步骤1中的被分出的jar包从项目libs文件夹下删除,将合并后的jar包依照外部jar的方式引入项目,android.jar就是采用了此种依赖方式
项目--右键--Build Path --Configure Build Path --- Libraries ---AddExternal JARs
6、在项目的Application中添加下面的方法
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
dexTool();
}
/**
* Copy the following code and calldexTool() after super.onCreate() in
* Application.onCreate()
* <p>
* This method hacks the defaultPathClassLoader and load the secondary dex
* file as it's parent.
*/
@SuppressLint("NewApi")
private void dexTool() {
File dexDir = newFile(getFilesDir(), "dlibs");
dexDir.mkdir();
File dexFile = newFile(dexDir, "libs.apk");
File dexOpt = newFile(dexDir, "opt");
dexOpt.mkdir();
try {
InputStream ins = getAssets().open("libs.apk");
if (dexFile.length() != ins.available()) {
FileOutputStream fos = new FileOutputStream(dexFile);
byte[] buf = new byte[4096];
int l;
while ((l = ins.read(buf)) != -1) {
fos.write(buf, 0, l);
}
fos.close();
}
ins.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
ClassLoader cl =getClassLoader();
ApplicationInfo ai =getApplicationInfo();
String nativeLibraryDir= null;
if(Build.VERSION.SDK_INT > 8) {
nativeLibraryDir = ai.nativeLibraryDir;
} else {
nativeLibraryDir = "/data/data/" + ai.packageName +"/lib/";
}
DexClassLoader dcl = newDexClassLoader(dexFile.getAbsolutePath(),
dexOpt.getAbsolutePath(), nativeLibraryDir, cl.getParent());
try {
Field f = ClassLoader.class.getDeclaredField("parent");
f.setAccessible(true);
f.set(cl, dcl);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
注:Application 中的静态全局变量会比MutiDex的 instal()方法优先加载,所以建议避免在 Application类中使用引用classes.dex文件的静态变量
至此,问题解决。