助力软件开发企业降本增效 PHP / java源码系统,只需一次付费,代码终身使用! 广告
四、加载补丁 4.1 思路 通过上一篇博文,我们知道dex 保存在这个位置 ``` BaseDexClassLoader–>pathList–>dexElements ``` apk 的classes.dex 可以从应用本身的DexClassLoader 中获取。 path_dex 的dex 需要new 一个DexClassLoader 加载后再获取。 分别通过反射取出dex 文件,重新合并成一个数组,然后赋值给盈通本身的ClassLoader 的dexElements 4.2 代码实现 加载外部dex,我们可以在Application 中操作。 首先新建一个HotPatchApplication,然后在清单文件中配置,顺便加上读取sdcard 的权限,因为补丁就保存在那里。 HotPatchApplication 代码如下: ``` package com.aitsuki.hotpatchdemo; import android.app.Application;import android.os.Environment;import andr oid.util.Log;import java.io.File;import java.lang.reflect.Array;import j ava.lang.reflect.Field;import dalvik.system.DexClassLoader; /** * Created by hp on 2016/4/6. */ public class HotPatchApplication extends Application { @Override public void onCreate() { super.onCreate(); // 获取补丁,如果存在就执行注入操作 String dexPath = Environment.getExternalStorageDirectory().getAb solutePath().concat("/patch_dex.jar"); File file = new File(dexPath); if (file.exists()) { inject(dexPath); } else { Log.e("BugFixApplication", dexPath + "不存在"); } } /** * 要注入的dex 的路径 * * @param path */ private void inject(String path) { try { // 获取classes 的dexElements Class<?> cl = Class.forName("dalvik.system.BaseDexClassLoader "); Object pathList = getField(cl, "pathList", getClassLoader()); Object baseElements = getField(pathList.getClass(), "dexEleme nts", pathList); // 获取patch_dex 的dexElements(需要先加载dex) String dexopt = getDir("dexopt", 0).getAbsolutePath(); DexClassLoader dexClassLoader = new DexClassLoader(path, dexo pt, dexopt, getClassLoader()); Object obj = getField(cl, "pathList", dexClassLoader); Object dexElements = getField(obj.getClass(), "dexElements", obj); // 合并两个Elements Object combineElements = combineArray(dexElements, baseElemen ts); // 将合并后的Element 数组重新赋值给app 的classLoader setField(pathList.getClass(), "dexElements", pathList, combin eElements); //======== 以下是测试是否成功注入================= Object object = getField(pathList.getClass(), "dexElements", pathList); int length = Array.getLength(object); Log.e("BugFixApplication", "length = " + length); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } /** * 通过反射获取对象的属性值 */ private Object getField(Class<?> cl, String fieldName, Object object) throws NoSuchFieldException, IllegalAccessException { Field field = cl.getDeclaredField(fieldName); field.setAccessible(true); return field.get(object); } /** * 通过反射设置对象的属性值 */ private void setField(Class<?> cl, String fieldName, Object object, O bject value) throws NoSuchFieldException, IllegalAccessException { Field field = cl.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value); } /** * 通过反射合并两个数组 */ private Object combineArray(Object firstArr, Object secondArr) { int firstLength = Array.getLength(firstArr); int secondLength = Array.getLength(secondArr); int length = firstLength + secondLength; Class<?> componentType = firstArr.getClass().getComponentType(); Object newArr = Array.newInstance(componentType, length); for (int i = 0; i < length; i++) { if (i < firstLength) { Array.set(newArr, i, Array.get(firstArr, i)); } else { Array.set(newArr, i, Array.get(secondArr, i - firstLengt h)); } } return newArr; } } ```