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);
}
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);
}
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;
}
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;
}
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) {
}
}
Aggregations