DexClassLoader自定义加载Assets目录下的dex、jar文件
本帖最后由 小白 于 2015-3-7 12:40 编辑就像网上网上有些朋友说的 dex文件的方法数貌似有上限,在网上找了好久也没找到可以完全把整个dex文件放在外部加载的方法 下面这个方法,是我从某个游戏中提取的,贴出代码,如果有错误之处,还望指点出来
转自:http://blog.csdn.net/zhuanshenai/article/details/43890235小坑说了:过年还在敲代码,活该没对象{:5_124:}
package com.example.dextest;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import dalvik.system.DexClassLoader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Myapp extends Application {
private static String AssetsDexFilePath = "_data";// Assets文件夹下的jar文件
private static String DexDir = "dex";
private static String ExtractedDexFileName = "_data.jar";// 导出
private static String TAG = "packer";
private Application mApp;
//ContextWrapper contextWrapper;
public Myapp() {
super();
}
@Override
public void onTerminate() {
// TODO Auto-generated method stub
super.onTerminate();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
if (this.mApp != null) {
this.mApp.onConfigurationChanged(newConfig);
}
}
@Override
public void onLowMemory() {
// TODO Auto-generated method stub
super.onLowMemory();
if(this.mApp != null) {
this.mApp.onLowMemory();
}
}
@Override
public void onTrimMemory(int level) {
// TODO Auto-generated method stub
super.onTrimMemory(level);
if(this.mApp != null) {
this.mApp.onTerminate();
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
copyDex();
String dexfilepath = getDir(DexDir, 0).getPath();
setApkClassLoader(new DexClassLoader(getDir(DexDir, 0).getPath() + "/" + ExtractedDexFileName, dexfilepath, getApplicationInfo().nativeLibraryDir, getClassLoader()));
//如果程序原来存在application 下面这个 就是替换原来application
//this.mApp = this.getClassLoader().loadClass(this.getPackageManager().getApplicationInfo( this.getPackageName(), 128).metaData.getString("packerApp")).newInstance();
Method v7;
try {
v7 = Class.forName("android.content.ContextWrapper").getDeclaredMethod("attachBaseContext",
Context.class);
v7.setAccessible(true);
v7.invoke(this);
v7.setAccessible(false);
/*如果存在原来的application
*v7.invoke(this.mApp, this);
*v7.setAccessible(false);
*this.mApp.onCreate();
*
*/
//this.mApp.onCreate();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**类加载器
* @param paramClassLoader
*/
@SuppressWarnings("unused")
private void setApkClassLoader(ClassLoader paramClassLoader) {
try {
Class localClass = Class.forName("android.app.ActivityThread");
Object localObject1 = localClass.getMethod("currentActivityThread", new Class).invoke(null, new Object);
Field localField1 = localClass.getDeclaredField("mPackages");
localField1.setAccessible(true);
Object localObject2 = localField1.get(localObject1);
localField1.setAccessible(false);
Method localMethod = localObject2.getClass().getMethod("get", new Class[] { Object.class });
Object[] arrayOfObject = new Object;
arrayOfObject = getPackageName();
Object localObject3 = ((WeakReference)localMethod.invoke(localObject2, arrayOfObject)).get();
Field localField2 = localObject3.getClass().getDeclaredField("mClassLoader");
localField2.setAccessible(true);
localField2.set(localObject3, paramClassLoader);
localField2.setAccessible(false);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 2");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 3");
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 4");
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 5");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 6");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "err 1");
}
}
/**
* 复制要加载jar文件
*/
private void copyDex() {
deleteFile(DexDir);// 如果文件存在则删除文件
File dexFile = getDir(DexDir, 0);// 需要导出的的文件路径
try {
InputStream localInputStream = getAssets().open(AssetsDexFilePath);// 获取Assets下的文件
FileOutputStream localFileOutputStream = new FileOutputStream(new File(dexFile,
ExtractedDexFileName));
byte[] arrayOfByte = new byte;
//int i = localInputStream.read(arrayOfByte);
for (;;)
{
int i = localInputStream.read(arrayOfByte);
if (i == -1) {
break;
}
localFileOutputStream.write(arrayOfByte, 0, i);
localFileOutputStream.flush();
}
localFileOutputStream.close();
localInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG, "exception in copyDex: " + e.toString());
return;
}
}
}
附件地址:http://pan.baidu.com/s/1bn0Hs7P
{:4_97:}大过年的 学习,manifest文件是否需要相应修改?楼主能否传个完整工程,只贴主要代码不好学习测试呀:(
感谢! 本帖最后由 小白 于 2015-3-7 12:37 编辑
wutp 发表于 2015-3-6 17:31
学习,manifest文件是否需要相应修改?楼主能否传个完整工程,只贴主要代码不好学习测试呀:(
感谢! ...
manifest application标签要把 这个类即: android:name="com.example.dextest.Myapp"设置为全局变量
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="com.example.dextest.Myapp" >我在帖子后面上传了一个测试工程 要注意的原来的dex文件要压缩成zip文件
谢谢,试了下测试工程,需要把assets/_data 文件改名为 data后,显示了helloworld,这是正常状态吗?
data文件是一个helloworld的DEX文件(ZIP压缩过)? wutp 发表于 2015-3-12 15:35
谢谢,试了下测试工程,需要把assets/_data 文件改名为 data后,显示了helloworld,这是正常状态吗?
data ...
正常的,这是个,测试工程, 经过zip压缩的的的 然后 复制到assets文件夹即可 我把自己写的APK的 DEX文件压缩zip,更名为data放在assets文件夹后,运行报错:
03-13 05:19:38.190: E/AndroidRuntime(1447): FATAL EXCEPTION: main
03-13 05:19:38.190: E/AndroidRuntime(1447): Process: com.example.sodex, PID: 1447
03-13 05:19:38.190: E/AndroidRuntime(1447): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.sodex/com.example.sodex.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "com.example.sodex.MainActivity" on path: DexPathList[,nativeLibraryDirectories=]
看你的测试代码中也没有将zip 解压缩还原为dex 的过程,是不是不应该压缩为zip?
给你发了站内信息,有空私聊,请教!谢谢!
页:
[1]