package me.ele.amigo;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.zip.ZipFile;
import dalvik.system.DexClassLoader;
public class AmigoClassLoader extends DexClassLoader {
private static final String TAG = AmigoClassLoader.class.getName();
private ZipFile zipFile;
private File patchApk;
public AmigoClassLoader(String patchApkPath, String dexPath, String optimizedDirectory, String
libraryPath, ClassLoader parent) {
super(dexPath, optimizedDirectory, libraryPath, parent);
try {
patchApk = new File(patchApkPath);
zipFile = new ZipFile(patchApkPath);
} catch (IOException e) {
e.printStackTrace();
zipFile = null;
}
}
public static AmigoClassLoader newInstance(Context context, String checksum) {
return new AmigoClassLoader(PatchApks.getInstance(context).patchPath(checksum),
getDexPath(context, checksum),
AmigoDirs.getInstance(context).dexOptDir(checksum).getAbsolutePath(),
getLibraryPath(context, checksum),
AmigoClassLoader.class.getClassLoader().getParent());
}
private static String getLibraryPath(Context context, String checksum) {
return AmigoDirs.getInstance(context).libDir(checksum).getAbsolutePath();
}
private static String joinPath(File folder) {
StringBuilder path = new StringBuilder();
File[] libFiles = folder.listFiles();
if (libFiles == null || libFiles.length == 0) {
return null;
}
for (File libFile : libFiles) {
path.append(File.pathSeparatorChar);
path.append(libFile.getAbsolutePath());
}
return path.toString();
}
private static String getDexPath(Context context, String checksum) {
if (Build.VERSION.SDK_INT >= 21) {
return PatchApks.getInstance(context).patchPath(checksum);
}
String dexPath = joinPath(AmigoDirs.getInstance(context).dexDir(checksum));
return dexPath != null ? dexPath : PatchApks.getInstance(context).patchPath(checksum);
}
@Override
protected URL findResource(String name) {
if ((zipFile == null) || (zipFile.getEntry(name) == null)) {
return null;
}
try {
/*
* File.toURL() is compliant with RFC 1738 in
* always creating absolute path names. If we
* construct the URL by concatenating strings, we
* might end up with illegal URLs for relative
* names.
*/
return new URL("jar:" + patchApk.toURL() + "!/" + name);
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
return super.loadClass(name);
} catch (ClassNotFoundException e) {
if (!name.startsWith("me.ele.amigo")) {
throw e;
}
Log.d(TAG, "loadClass: can't find amigo-lib in the patch apk, trying to load ["
+ name + "] from original classloader");
return AmigoClassLoader.class.getClassLoader().loadClass(name);
}
}
}