Android 핫 픽스 구현 방법 및 방법
public class DexClassLoader extends Base DexClassLoader {지정한 dex 파일을 불러올 수 있습니다. (제한: 프로그램의 디렉터리 아래에 있어야 하기 때문에 다운로드하려면 이 디렉터리에 복사해야 합니다.)
둘.분명히 우리는 DexClassLoader를 사용하여 수요를 실현해야 한다
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(parent);
this.originalPath = dexPath;
this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
}
DexPathList
public DexPathList(ClassLoader definingContext, String dexPath,
String libraryPath, File optimizedDirectory) {
……
this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory);
}
private static Element[] makeDexElements(ArrayList files,
File optimizedDirectory) {
ArrayList elements = new ArrayList();
for (File file : files) {
ZipFile zip = null;
DexFile dex = null;
String name = file.getName();
if (name.endsWith(DEX_SUFFIX)) {
dex = loadDexFile(file, optimizedDirectory);
} else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX)
|| name.endsWith(ZIP_SUFFIX)) {
zip = new ZipFile(file);
}
……
if ((zip != null) || (dex != null)) {
elements.add(new Element(file, zip, dex));
}
}
return elements.toArray(new Element[elements.size()]);
}
private static DexFile loadDexFile(File file, File optimizedDirectory)
throws IOException {
if (optimizedDirectory == null) {
return new DexFile(file);
} else {
String optimizedPath = optimizedPathFor(file, optimizedDirectory);
return DexFile.loadDex(file.getPath(), optimizedPath, 0);
}
}
/**
* Converts a dex/jar file path and an output directory to an
* output file path for an associated optimized dex file.
*/
private static String optimizedPathFor(File path,
File optimizedDirectory) {
String fileName = path.getName();
if (!fileName.endsWith(DEX_SUFFIX)) {
int lastDot = fileName.lastIndexOf(".");
if (lastDot < 0) {
fileName += DEX_SUFFIX;
} else {
StringBuilder sb = new StringBuilder(lastDot + 4);
sb.append(fileName, 0, lastDot);
sb.append(DEX_SUFFIX);
fileName = sb.toString();
}
}
File result = new File(optimizedDirectory, fileName);
return result.getPath();
}
optimizedDirectory dex , DexFile , null, dex DexFile
。
클래스를 로드하는 과정: ClassLoader는 loadClass를 통해 필요한 클래스를 로드합니다.
public Class> loadClass(String className) throws ClassNotFoundException {
return loadClass(className, false);
}
protected Class> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class> clazz = findLoadedClass(className);
if (clazz == null) {
ClassNotFoundException suppressed = null;
try {
clazz = parent.loadClass(className, false);
} catch (ClassNotFoundException e) {
suppressed = e;
}
if (clazz == null) {
try {
clazz = findClass(className);
} catch (ClassNotFoundException e) {
e.addSuppressed(suppressed);
throw e;
}
}
}
return clazz;
}
마지막으로 DexPathList의findClass를 호출했습니다.
public Class findClass(String name) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
Class clazz = dex.loadClassBinaryName(name, definingContext);
if (clazz != null) {
return clazz;
}
}
}
return null;
}
위 코드에서 보듯이 요소에서class를 찾으면 for 순환이 종료됩니다. 따라서 dexElements라는 집합을 수정하면 됩니다. 우리가 만든 dexElements와 원시적인 dexElements를 합치면 됩니다.dexA: 원래 app의 dex 파일 dexB: 패치 dex 파일로 여러 개가 가능합니다.먼저 다운로드한 dex 파일을 파일 형식으로 집합에 저장합니다
// dex
File fileDir = context.getDir(MyConstants.DEX_DIR,Context.MODE_PRIVATE);
File[] listFiles = fileDir.listFiles();
for(File file:listFiles){
if(file.getName().startsWith("classes")&&file.getName().endsWith(".dex")){
loadedDex.add(file);//
}
}
2. 반사로dexA,dexB의classLoader,dexA의classLoader는PathClassLoader,dexB의classLoader는dexClassLoader로 가져오기
PathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader();
for (File dex : loadedDex) {
//2. dex 。
DexClassLoader classLoader = new DexClassLoader(
dex.getAbsolutePath(),//String dexPath,
fopt.getAbsolutePath(),//String optimizedDirectory,
null,//String libraryPath,
pathLoader//ClassLoader parent
);
}
3. classloader를 통해 dexA와 dexB의 pathList 가져오기
Object dexObj = getPathList(classLoader);
Object pathObj = getPathList(pathLoader);
4. pathList를 통해 dexA와 dexB의 dexElements를 가져오고 이 두 가지를 합친다
Object mDexElementsList = getDexElements(dexObj);
Object pathDexElementsList = getDexElements(pathObj);
//
Object dexElements = combineArray(mDexElementsList,pathDexElementsList);
5. 병합된 dexElements를 dexA의classLoader의pathList의dexElements에 값을 부여
Object mDexElementsList = getDexElements(dexObj);
Object pathDexElementsList = getDexElements(pathObj);
//
Object dexElements = combineArray(mDexElementsList,pathDexElementsList);
// PathList lement[] dexElements;
Object pathList = getPathList(pathLoader);
setField(pathList,pathList.getClass(),"dexElements",dexElements);
그러면 구체적인 절차는 이미 완성되었다.
6.dex백을 어떻게 칠 수 있습니까?dx를 통과하다.bat 이 시스템에서 제공하는 도구는
1. MyTestClass.class
com\app\build\intermediates\bin\MyTestClass.class
2. dx.bat
Android\sdk\build-tools\23.0.3\dx.bat
3.
dx --dex --output=D:\Users\jiang\Desktop\dex\classes2.dex D:\Users\jiang\Desktop\dex
:
--output=D:\Users\jiang\Desktop\dex\classes2.dex
D:\Users\jiang\Desktop\dex class ( , class)
코드 주소는 다음과 같습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.