小白 发表于 2015-2-21 15:46:50

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

默小坑 发表于 2015-2-21 22:34:40

{:4_97:}大过年的

wutp 发表于 2015-3-6 17:31:06

学习,manifest文件是否需要相应修改?楼主能否传个完整工程,只贴主要代码不好学习测试呀:(

感谢!

小白 发表于 2015-3-7 12:36:03

本帖最后由 小白 于 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文件

wutp 发表于 2015-3-12 15:35:00

谢谢,试了下测试工程,需要把assets/_data 文件改名为 data后,显示了helloworld,这是正常状态吗?
data文件是一个helloworld的DEX文件(ZIP压缩过)?

小白 发表于 2015-3-12 19:28:13

wutp 发表于 2015-3-12 15:35
谢谢,试了下测试工程,需要把assets/_data 文件改名为 data后,显示了helloworld,这是正常状态吗?
data ...

正常的,这是个,测试工程, 经过zip压缩的的的 然后 复制到assets文件夹即可

wutp 发表于 2015-3-13 17:35:19

我把自己写的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]
查看完整版本: DexClassLoader自定义加载Assets目录下的dex、jar文件