Search in sources :

Example 56 with DexFile

use of dalvik.system.DexFile in project AndroidLife by CaMnter.

the class BaseDexClassLoaderHooker method patchClassLoader.

@SuppressWarnings("DanglingJavadoc")
public static void patchClassLoader(@NonNull final ClassLoader classLoader, @NonNull final File apkFile, @NonNull final File optDexFile) throws IllegalAccessException, NoSuchMethodException, IOException, InvocationTargetException, InstantiationException, NoSuchFieldException, ClassNotFoundException {
    // 获取 BaseDexClassLoader # DexPathList pathList
    final Field pathListField = DexClassLoader.class.getSuperclass().getDeclaredField("pathList");
    pathListField.setAccessible(true);
    final Object pathList = pathListField.get(classLoader);
    // 获取 DexPathList # Element[] dexElements
    final Field dexElementArray = pathList.getClass().getDeclaredField("dexElements");
    dexElementArray.setAccessible(true);
    final Object[] dexElements = (Object[]) dexElementArray.get(pathList);
    // Element 类型
    final Class<?> elementClass = dexElements.getClass().getComponentType();
    // 用于替换 PathList # Element[] dexElements
    final Object[] newElements = (Object[]) Array.newInstance(elementClass, dexElements.length + 1);
    /**
     * <= 4.0.0
     *
     * no method
     *
     * >= 4.0.0
     *
     * Element(File file, ZipFile zipFile, DexFile dexFile)
     *
     * ---
     *
     * >= 5.0.0
     *
     * Element(File file, boolean isDirectory, File zip, DexFile dexFile)
     *
     * ---
     *
     * >= 8.0.0
     *
     * @Deprecated
     * Element(File dir, boolean isDirectory, File zip, DexFile dexFile)
     * Element(DexFile dexFile, File dexZipPath)
     */
    final int sdkVersion = Build.VERSION.SDK_INT;
    if (sdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        throw new RuntimeException("[BaseDexClassLoaderHooker]   the sdk version must >= 14 (4.0.0)");
    }
    final Object element;
    final Constructor<?> constructor;
    if (sdkVersion >= Build.VERSION_CODES.O) {
        // >= 8.0.0
        // DexFile dexFile, File dexZipPath
        constructor = elementClass.getConstructor(DexFile.class, File.class);
        element = constructor.newInstance(DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0), apkFile);
    } else if (sdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
        // >= 5.0.0
        // File file, boolean isDirectory, File zip, DexFile dexFile
        constructor = elementClass.getConstructor(File.class, boolean.class, File.class, DexFile.class);
        element = constructor.newInstance(apkFile, false, apkFile, DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0));
    } else {
        // >= 4.0.0
        // File file, ZipFile zipFile, DexFile dexFile
        constructor = elementClass.getConstructor(File.class, ZipFile.class, DexFile.class);
        element = constructor.newInstance(apkFile, new ZipFile(apkFile), DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0));
    }
    final Object[] toAddElementArray = new Object[] { element };
    // 把原始的 elements 复制进去
    System.arraycopy(dexElements, 0, newElements, 0, dexElements.length);
    // 把插件的 element  复制进去
    System.arraycopy(toAddElementArray, 0, newElements, dexElements.length, toAddElementArray.length);
    // 替换
    dexElementArray.set(pathList, newElements);
}
Also used : Field(java.lang.reflect.Field) ZipFile(java.util.zip.ZipFile) DexClassLoader(dalvik.system.DexClassLoader) DexFile(dalvik.system.DexFile) ZipFile(java.util.zip.ZipFile) File(java.io.File) DexFile(dalvik.system.DexFile)

Example 57 with DexFile

use of dalvik.system.DexFile in project AndroidLife by CaMnter.

the class BaseDexClassLoaderHooker method patchClassLoader.

@SuppressWarnings("DanglingJavadoc")
public static void patchClassLoader(@NonNull final ClassLoader classLoader, @NonNull final File apkFile, @NonNull final File optDexFile) throws IllegalAccessException, NoSuchMethodException, IOException, InvocationTargetException, InstantiationException, NoSuchFieldException, ClassNotFoundException {
    // 获取 BaseDexClassLoader # DexPathList pathList
    final Field pathListField = DexClassLoader.class.getSuperclass().getDeclaredField("pathList");
    pathListField.setAccessible(true);
    final Object pathList = pathListField.get(classLoader);
    // 获取 DexPathList # Element[] dexElements
    final Field dexElementArray = pathList.getClass().getDeclaredField("dexElements");
    dexElementArray.setAccessible(true);
    final Object[] dexElements = (Object[]) dexElementArray.get(pathList);
    // Element 类型
    final Class<?> elementClass = dexElements.getClass().getComponentType();
    // 用于替换 PathList # Element[] dexElements
    final Object[] newElements = (Object[]) Array.newInstance(elementClass, dexElements.length + 1);
    /**
     * <= 4.0.0
     *
     * no method
     *
     * >= 4.0.0
     *
     * Element(File file, ZipFile zipFile, DexFile dexFile)
     *
     * ---
     *
     * >= 5.0.0
     *
     * Element(File file, boolean isDirectory, File zip, DexFile dexFile)
     *
     * ---
     *
     * >= 8.0.0
     *
     * @Deprecated
     * Element(File dir, boolean isDirectory, File zip, DexFile dexFile)
     * Element(DexFile dexFile, File dexZipPath)
     */
    final int sdkVersion = Build.VERSION.SDK_INT;
    if (sdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        throw new RuntimeException("[BaseDexClassLoaderHooker]   the sdk version must >= 14 (4.0.0)");
    }
    final Object element;
    final Constructor<?> constructor;
    if (sdkVersion >= Build.VERSION_CODES.O) {
        // >= 8.0.0
        // DexFile dexFile, File dexZipPath
        constructor = elementClass.getConstructor(DexFile.class, File.class);
        element = constructor.newInstance(DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0), apkFile);
    } else if (sdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
        // >= 5.0.0
        // File file, boolean isDirectory, File zip, DexFile dexFile
        constructor = elementClass.getConstructor(File.class, boolean.class, File.class, DexFile.class);
        element = constructor.newInstance(apkFile, false, apkFile, DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0));
    } else {
        // >= 4.0.0
        // File file, ZipFile zipFile, DexFile dexFile
        constructor = elementClass.getConstructor(File.class, ZipFile.class, DexFile.class);
        element = constructor.newInstance(apkFile, new ZipFile(apkFile), DexFile.loadDex(apkFile.getCanonicalPath(), optDexFile.getAbsolutePath(), 0));
    }
    final Object[] toAddElementArray = new Object[] { element };
    // 把原始的 elements 复制进去
    System.arraycopy(dexElements, 0, newElements, 0, dexElements.length);
    // 把插件的 element  复制进去
    System.arraycopy(toAddElementArray, 0, newElements, dexElements.length, toAddElementArray.length);
    // 替换
    dexElementArray.set(pathList, newElements);
}
Also used : Field(java.lang.reflect.Field) ZipFile(java.util.zip.ZipFile) DexClassLoader(dalvik.system.DexClassLoader) DexFile(dalvik.system.DexFile) ZipFile(java.util.zip.ZipFile) File(java.io.File) DexFile(dalvik.system.DexFile)

Example 58 with DexFile

use of dalvik.system.DexFile in project AndroidLife by CaMnter.

the class ClassUtils method tryLoadInstantRunDexFile.

private static List<String> tryLoadInstantRunDexFile(ApplicationInfo applicationInfo) {
    List<String> instantRunSourcePaths = new ArrayList<>();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && null != applicationInfo.splitSourceDirs) {
        // add the splite apk, normally for InstantRun, and newest version.
        instantRunSourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
        Log.d("ClassUtils", "Found InstantRun support");
    } else {
        try {
            // This man is reflection from Google instant run sdk, he will tell me where the dex files go.
            Class pathsByInstantRun = Class.forName("com.android.tools.fd.runtime.Paths");
            Method getDexFileDirectory = pathsByInstantRun.getMethod("getDexFileDirectory", String.class);
            String instantRunDexPath = (String) getDexFileDirectory.invoke(null, applicationInfo.packageName);
            File instantRunFilePath = new File(instantRunDexPath);
            if (instantRunFilePath.exists() && instantRunFilePath.isDirectory()) {
                File[] dexFile = instantRunFilePath.listFiles();
                for (File file : dexFile) {
                    if (null != file && file.exists() && file.isFile() && file.getName().endsWith(".dex")) {
                        instantRunSourcePaths.add(file.getAbsolutePath());
                    }
                }
                Log.d("ClassUtils", "Found InstantRun support");
            }
        } catch (Exception e) {
            Log.e("ClassUtils", "InstantRun support error, " + e.getMessage());
        }
    }
    return instantRunSourcePaths;
}
Also used : ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) DexFile(dalvik.system.DexFile) File(java.io.File) IOException(java.io.IOException)

Example 59 with DexFile

use of dalvik.system.DexFile in project sugar by satyan.

the class MultiDexHelper method getSourcePaths.

/**
 * get all the dex path
 *
 * @return all the dex path, including the ones in the newly added instant-run folder
 * @throws PackageManager.NameNotFoundException
 * @throws IOException
 */
public static List<String> getSourcePaths() throws PackageManager.NameNotFoundException, IOException {
    ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(getPackageName(), 0);
    File sourceApk = new File(applicationInfo.sourceDir);
    File dexDir = new File(applicationInfo.dataDir, SECONDARY_FOLDER_NAME);
    // default instant-run dir
    File instantRunDir = new File(applicationInfo.dataDir, INSTANT_RUN_DEX_DIR_PATH);
    List<String> sourcePaths = new ArrayList<>();
    // add the default apk path
    sourcePaths.add(applicationInfo.sourceDir);
    if (instantRunDir.exists()) {
        // check if app using instant run
        for (final File dexFile : instantRunDir.listFiles()) {
            // add all sources from instan-run
            sourcePaths.add(dexFile.getAbsolutePath());
        }
    }
    // the prefix of extracted file, ie: test.classes
    String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;
    // the total dex numbers
    int totalDexNumber = getMultiDexPreferences().getInt(KEY_DEX_NUMBER, 1);
    for (int secondaryNumber = 2; secondaryNumber <= totalDexNumber; secondaryNumber++) {
        // for each dex file, ie: test.classes2.zip, test.classes3.zip...
        String fileName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX;
        File extractedFile = new File(dexDir, fileName);
        if (extractedFile.isFile()) {
            sourcePaths.add(extractedFile.getAbsolutePath());
        // we ignore the verify zip part
        }
    }
    return sourcePaths;
}
Also used : ApplicationInfo(android.content.pm.ApplicationInfo) ArrayList(java.util.ArrayList) DexFile(dalvik.system.DexFile) File(java.io.File)

Example 60 with DexFile

use of dalvik.system.DexFile in project RocooFix by dodola.

the class RocooFix method applyPatchRuntime.

/**
 * 从指定目录加载补丁
 *
 * @param context
 * @param dexPath
 */
public static void applyPatchRuntime(Context context, String dexPath) {
    if (context == null) {
        return;
    } else {
        context = context.getApplicationContext();
    }
    try {
        File file = new File(dexPath);
        File optfile = new File(mOptDir, file.getName());
        final DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(), optfile.getAbsolutePath(), Context.MODE_PRIVATE);
        ClassLoader classLoader = context.getClassLoader();
        ClassLoader patchClassLoader = new ClassLoader(classLoader) {

            @Override
            protected Class<?> findClass(String className) throws ClassNotFoundException {
                Class<?> clazz = dexFile.loadClass(className, this);
                if (clazz == null && (className.startsWith("com.dodola.rocoofix") || className.startsWith("com.lody.legend") || className.startsWith("com.alipay.euler.andfix"))) {
                    return Class.forName(className);
                }
                if (clazz == null) {
                    throw new ClassNotFoundException(className);
                }
                return clazz;
            }
        };
        Enumeration<String> entrys = dexFile.entries();
        Class<?> clazz = null;
        while (entrys.hasMoreElements()) {
            String entry = entrys.nextElement();
            clazz = dexFile.loadClass(entry, patchClassLoader);
            if (clazz != null) {
                fixClass(clazz, classLoader);
            }
        }
    } catch (IOException e) {
    }
}
Also used : IOException(java.io.IOException) ZipFile(java.util.zip.ZipFile) DexFile(dalvik.system.DexFile) File(java.io.File) DexFile(dalvik.system.DexFile)

Aggregations

DexFile (dalvik.system.DexFile)62 File (java.io.File)34 IOException (java.io.IOException)28 ArrayList (java.util.ArrayList)18 Field (java.lang.reflect.Field)13 Method (java.lang.reflect.Method)13 ZipFile (java.util.zip.ZipFile)13 DexClassLoader (dalvik.system.DexClassLoader)9 Enumeration (java.util.Enumeration)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 ApplicationInfo (android.content.pm.ApplicationInfo)3 NClassLoader (android.taobao.atlas.startup.NClassLoader)2 URL (java.net.URL)2 HashSet (java.util.HashSet)2 Application (android.app.Application)1 ActivityNotFoundException (android.content.ActivityNotFoundException)1 NameNotFoundException (android.content.pm.PackageManager.NameNotFoundException)1 Main (com.android.dx.command.dexer.Main)1 Action (com.jia.base.annotation.Action)1 Tinker (com.tencent.tinker.lib.tinker.Tinker)1