1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
| package com.york.rexiufu.rexiufu;
import android.content.Context; import android.os.Environment; import android.support.annotation.NonNull; import com.york.rexiufu.utils.LogUtil;
import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.HashSet;
import dalvik.system.DexClassLoader; import dalvik.system.PathClassLoader;
public class FixDexUtil {
private static final String DEX_SUFFIX = ".dex"; private static final String APK_SUFFIX = ".apk"; private static final String JAR_SUFFIX = ".jar"; private static final String ZIP_SUFFIX = ".zip"; public static final String DEX_DIR = "odex"; private static final String OPTIMIZE_DEX_DIR = "optimize_dex"; private static HashSet<File> loadedDex = new HashSet<>();
static { loadedDex.clear(); }
public static void loadFixedDex(Context context) { loadFixedDex(context, null); }
public static void loadFixedDex(Context context, File patchFilesDir) { LogUtil.e("开始修复。。。。。。"); doDexInject(context, loadedDex); }
public static boolean isGoingToFix(@NonNull Context context) { boolean canFix = false; File externalStorageDirectory = Environment.getExternalStorageDirectory();
File fileDir = externalStorageDirectory != null ? new File(externalStorageDirectory, "YorkFix") : new File(context.getFilesDir(), DEX_DIR);
File[] listFiles = fileDir.listFiles(); if (listFiles != null) { for (File file : listFiles) { if (file.getName().startsWith("my") && (file.getName().endsWith(DEX_SUFFIX) || file.getName().endsWith(APK_SUFFIX) || file.getName().endsWith(JAR_SUFFIX) || file.getName().endsWith(ZIP_SUFFIX))) {
loadedDex.add(file); canFix = true; } } } return canFix; }
private static void doDexInject(Context appContext, HashSet<File> loadedDex) { String optimizeDir = appContext.getFilesDir().getAbsolutePath() + File.separator + OPTIMIZE_DEX_DIR;
File fopt = new File(optimizeDir); if (!fopt.exists()) { fopt.mkdirs(); } try { PathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader(); for (File dex : loadedDex) { DexClassLoader dexLoader = new DexClassLoader( dex.getAbsolutePath(), fopt.getAbsolutePath(), null, pathLoader );
Object dexPathList = getPathList(dexLoader); Object pathPathList = getPathList(pathLoader); Object leftDexElements = getDexElements(dexPathList); Object rightDexElements = getDexElements(pathPathList); Object dexElements = combineArray(leftDexElements, rightDexElements);
Object pathList = getPathList(pathLoader); setField(pathList, pathList.getClass(), "dexElements", dexElements); } LogUtil.e("修复完成"); } catch (Exception e) { e.printStackTrace(); } }
private static void setField(Object obj, Class<?> cl, String field, Object value) throws NoSuchFieldException, IllegalAccessException { Field declaredField = cl.getDeclaredField(field); declaredField.setAccessible(true); declaredField.set(obj, value); }
private static Object getField(Object obj, Class<?> cl, String field) throws NoSuchFieldException, IllegalAccessException { Field localField = cl.getDeclaredField(field); localField.setAccessible(true); return localField.get(obj); }
private static Object getPathList(Object baseDexClassLoader) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { return getField(baseDexClassLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList"); }
private static Object getDexElements(Object pathList) throws NoSuchFieldException, IllegalAccessException { return getField(pathList, pathList.getClass(), "dexElements"); }
private static Object combineArray(Object arrayLhs, Object arrayRhs) { Class<?> clazz = arrayLhs.getClass().getComponentType(); int i = Array.getLength(arrayLhs); int j = Array.getLength(arrayRhs); int k = i + j; Object result = Array.newInstance(clazz, k); System.arraycopy(arrayLhs, 0, result, 0, i); System.arraycopy(arrayRhs, 0, result, i, j); return result; } }
|