package com.android.hotfix;
import
android.app.Application;
import
java.io.
File
;
import
java.io.IOException;
import
java.lang.reflect.Array;
import
java.lang.reflect.Field;
import
java.lang.reflect.Method;
import
java.util.ArrayList;
import
java.util.
List
;
public
class
HotFix {
public static void installDex(Application myApp, String path){
/
/
获取类加载器
ClassLoader loader
=
myApp.getClassLoader();
/
/
获取到类加载器的Class
Class
cls
=
loader.getClass();
/
/
获取pathList对象
Field plField
=
null;
Object
pathList
=
null;
try
{
plField
=
cls
.getSuperclass().getDeclaredField(
"pathList"
);
plField.setAccessible(true);
pathList
=
plField.get(loader);
} catch (Exception e) {
e.printStackTrace();
}
/
/
获取Element数组
Object
[] dexElements
=
null;
Field dexField
=
null;
if
(pathList!
=
null){
try
{
dexField
=
pathList.getClass().getDeclaredField(
"dexElements"
);
dexField.setAccessible(true);
dexElements
=
(
Object
[]) dexField.get(pathList);
} catch (Exception e) {
e.printStackTrace();
}
}
/
/
获取补丁数组
Object
[] patchElements
=
makePatch(myApp,pathList,path);
if
(patchElements!
=
null && dexElements !
=
null){
/
/
合并两个数组
Object
[] newElements
=
(
Object
[]) Array.newInstance(dexElements[
0
].getClass(),dexElements.length
+
patchElements.length);
System.arraycopy(patchElements,
0
,newElements,
0
,patchElements.length);
System.arraycopy(dexElements,
0
,newElements,patchElements.length,dexElements.length);
/
/
替换合并后的数组
try
{
dexField.
set
(pathList,newElements);
} catch (Exception e) {
e.printStackTrace();
}
try
{
Object
[] testField
=
(
Object
[]) dexField.get(pathList);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private static
Object
[] makePatch(Application myApp,
Object
pathList, String path) {
Object
[] rst
=
null;
try
{
/
/
获取makeElements方法
/
/
Method makeMethod
=
pathList.getClass().getDeclaredMethod(
"makePathElements"
, java.util.
List
.
class
,java.io.
File
.
class
,java.util.
List
.
class
);
Method makeMethod
=
pathList.getClass().getDeclaredMethod(
"makeElements"
, java.util.
List
.
class
,java.io.
File
.
class
,java.util.
List
.
class
,boolean.
class
,ClassLoader.
class
);
/
/
参数准备
List
<
File
> dexFiles
=
new ArrayList<>();
File
dexFile
=
new
File
(path);
dexFiles.add(dexFile);
File
optimizedDirectory
=
myApp.getCacheDir();
List
<IOException> suppressedExceptions
=
new ArrayList<>();
/
/
调用方法
if
(makeMethod!
=
null) {
makeMethod.setAccessible(true);
/
/
return
(
Object
[]) makeMethod.invoke(pathList,dexFiles,optimizedDirectory,suppressedExceptions);
return
(
Object
[]) makeMethod.invoke(pathList,dexFiles,optimizedDirectory,suppressedExceptions,false,myApp.getClassLoader());
}
} catch (Exception e) {
e.printStackTrace();
}
return
null;
}
}