1、采用手动方式合并jar文件,将要合并的jar文件解压到同一目录下。然后将该目录压缩成libs.zip,再重命名为libs.jar。
合并jar包:
①将要合并的JAR包放到同一个文件夹下;
②命令行下定位到当前文件夹;
③通过jar解压命令将jar包全部解压,命令为>jar –xvfxx.jar;//xx 是目标jar包名。
④删除目录下的.jar文件,命令为>del /F *.jar;
⑤合并所有的.class文件至jar,命令为>jar –cvfMlibs.jar .,注意:jar .
2、使用Android SDK提供的dx工具将libs.jar转换为dex文件,命名为classes.dex。//classes 与后续代码里的classes.apk名字对应。
打开命令行工具,进入到dx.bat所在的目录下,执行命令
如:dx --dex --output=D:\test\classes.dex D:\test\libs.jar //注意空格
dx工具可以在Android SDK下找到,如\SDK\build-tools\23.0.1\dx.bat
D:\test\classes.dex为打包生成的dex文件的目标路径,D:\test\libs.jar为jar文件的路径
3、将上一步打包生成的classes.dex添加为压缩文件classes.zip,然后重命名为classes.apk
4、将classes.apk放入项目的assets文件夹下。
5.将步骤1中的被分出的jar包从项目libs文件夹下删除,将合并后的jar包依照外部jar的方式引入项目,android.jar就是采用了此种依赖方式。
项目--右键--Build Path--Configure Build Path --- Libraries ---AddExternal JARs
项目--右键--Build Path--Configure Build Path --- Libraries —AddJARs选择
assets文件下。//针对Window上开发,mac上打包。
6、在项目的Application中添加下面的方法
public classApp extends Application {
@Override
public void onCreate() {
super.onCreate();
dexTool();
}
/**
* Copy the following code andcalldexTool() after super.onCreate() in
* Application.onCreate()
* <p>
* This method hacks thedefaultPathClassLoader 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 = newFileOutputStream(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文件的静态变量
至此,问题解决。