下面列出了android.content.Context#getClassLoader ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Get all loaded external classes name in "classes2.dex", "classes3.dex" ....
*
* @return get all loaded external classes
*/
public List<String> getLoadedExternalDexClasses(Context context) {
try {
final List<String> externalDexClasses = getExternalDexClasses(context);
if (externalDexClasses != null && !externalDexClasses.isEmpty()) {
final ArrayList<String> classList = new ArrayList<>();
final java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[]{String.class});
m.setAccessible(true);
final ClassLoader cl = context.getClassLoader();
for (String clazz : externalDexClasses) {
if (m.invoke(cl, clazz) != null) {
classList.add(clazz.replaceAll("\\.", "/").replaceAll("$", ".class"));
}
}
return classList;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean isVivoCutout(Context context) {
if (!isVivo()) {
return false;
}
boolean ret = false;
try {
ClassLoader cl = context.getClassLoader();
Class ftFeature = cl.loadClass("android.util.FtFeature");
Method[] methods = ftFeature.getDeclaredMethods();
if (methods != null) {
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (method.getName().equalsIgnoreCase("isFeatureSupport")) {
ret = (boolean) method.invoke(ftFeature, NOTCH_IN_SCREEN_VOIO);
break;
}
}
}
} catch (Exception e) {
// ignore
}
return ret;
}
/**
* 用反射方式加载类
*
* @param context
* @param path
* @return
*/
public static Object loadClass(Context context, String path) {
try {
String dexPath = context.getApplicationInfo().sourceDir;
PathClassLoader pathClassLoader = new PathClassLoader(dexPath,
context.getClassLoader());
Class<?> c = Class.forName(path, true, pathClassLoader);
Object ret = c.newInstance();
return ret;
} catch (InstantiationException ex1) {
ex1.printStackTrace();
} catch (IllegalAccessException ex2) {
ex2.printStackTrace();
} catch (ClassNotFoundException ex3) {
ex3.printStackTrace();
}
return null;
}
@TargetApi(14)
private static void injectBelowApiLevel14(Context context, String str, String str2)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
DexClassLoader dexClassLoader =
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
dexClassLoader.loadClass(str2);
setField(obj, PathClassLoader.class, "mPaths",
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
"mRawDexPath")
));
setField(obj, PathClassLoader.class, "mFiles",
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
"mFiles")
));
setField(obj, PathClassLoader.class, "mZips",
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
"mZips")));
setField(obj, PathClassLoader.class, "mDexs",
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
"mDexs")));
obj.loadClass(str2);
}
/**
* api >= 14时,注入jar
*
* @param context application object
* @param dexPath lib path
* @return inject object
*/
private static InjectResult injectAboveEqualApiLevel14(Context context, String dexPath, String soPath) {
PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
File optDir = PluginInstaller.getPluginInjectRootPath(context);
FileUtils.checkOtaFileValid(optDir, new File(dexPath));
DexClassLoader dexClassLoader = new DexClassLoader(dexPath, optDir.getAbsolutePath(), soPath,
pathClassLoader);
InjectResult result = null;
// If version > 22 LOLLIPOP_MR1
if (Build.VERSION.SDK_INT > 22) {
result = injectAboveApiLevel22(pathClassLoader, dexClassLoader);
} else {
result = injectAboveEqualApiLevel14(pathClassLoader, dexClassLoader);
}
return result;
}
@TargetApi(14)
private static void injectBelowApiLevel14(Context context, String str, String str2)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
DexClassLoader dexClassLoader =
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
dexClassLoader.loadClass(str2);
setField(obj, PathClassLoader.class, "mPaths",
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
"mRawDexPath")
));
setField(obj, PathClassLoader.class, "mFiles",
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
"mFiles")
));
setField(obj, PathClassLoader.class, "mZips",
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
"mZips")));
setField(obj, PathClassLoader.class, "mDexs",
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
"mDexs")));
obj.loadClass(str2);
}
private String getProp(Context context, String property) {
try {
ClassLoader classLoader = context.getClassLoader();
Class<?> systemProperties = classLoader.loadClass("android.os.SystemProperties");
Method get = systemProperties.getMethod("get", String.class);
Object[] params = new Object[1];
params[0] = property;
return (String) get.invoke(systemProperties, params);
} catch (Exception exception) {
// empty catch
}
return null;
}
/**
* 启动 Service 时,从 Intent 中获取 ComponentName
*/
private static ComponentName getServiceComponentFromIntent(Context context, Intent intent) {
ClassLoader cl = context.getClassLoader();
String plugin = PluginFactory.fetchPluginName(cl);
/* Intent 中已指定 ComponentName */
if (intent.getComponent() != null) {
// 根据 Context 所带的插件信息,来填充 Intent 的 ComponentName 对象。具体见方法说明
return PluginClientHelper.getComponentNameByContext(context, intent.getComponent());
} else {
/* Intent 中已指定 Action,根据 action 解析出 ServiceInfo */
if (!TextUtils.isEmpty(intent.getAction())) {
ComponentList componentList = PluginFactory.queryPluginComponentList(plugin);
if (componentList != null) {
// 返回 ServiceInfo 和 Service 所在的插件
Pair<ServiceInfo, String> pair = componentList.getServiceAndPluginByIntent(context, intent);
if (pair != null) {
return new ComponentName(pair.second, pair.first.name);
}
}
} else {
if (LOG) {
LogDebug.d(PLUGIN_TAG, "PSS.startService(): No Component and no Action");
}
}
}
return null;
}
/**
* Loads Dexes
*
* @param cxt Application or Activity Context
* @param dexDir The Dex Directory: Example: {@code /data/data/com.beetalk/app_dex/}
* @param names
* @return
*/
private static boolean appendOdexesToClassPath(Context cxt, File dexDir, String[] names) {
// non-existing ZIP in classpath causes an exception on ICS
// so filter out the non-existent
String strDexDir = dexDir.getAbsolutePath();
ArrayList<String> zipPaths = new ArrayList<String>();
for (int i = 0; i < names.length; i++) {
String zipPath = strDexDir + '/' + names[i];
File f = new File(zipPath);
if (f.isFile()) {
zipPaths.add(zipPath);
}
}
String[] zipsOfDex = new String[zipPaths.size()];
zipPaths.toArray(zipsOfDex);
PathClassLoader pcl = (PathClassLoader) cxt.getClassLoader();
// do something dangerous
try {
if (Build.VERSION.SDK_INT < SDK_INT_ICS) {
FrameworkHack.appendDexListImplUnderICS(zipsOfDex, pcl, dexDir);
} else { // ICS+
boolean kitkatPlus = Build.VERSION.SDK_INT >= SDK_INT_KITKAT;
ArrayList<File> jarFiles = strings2Files(zipsOfDex);
FrameworkHack.appendDexListImplICS(jarFiles, pcl, dexDir, kitkatPlus);
}
// update theAppended if succeeded to prevent duplicated classpath entry
for (String jarName : names) {
theAppended.add(jarName);
}
Log.d(LOG_TAG, "appendOdexesToClassPath completed : " + pcl);
Log.d(LOG_TAG, "theAppended : " + theAppended);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return true;
}
/**
* 根据Context所带的插件信息,来填充Intent的ComponentName对象
* 若外界将Context.xxxService方法用PluginServiceClient代替(如编译工具所做的),则这里会做如下事情:
* 1、将外界传递的Intent为com.qihoo360.mobilesafe的包名,变成一个特定插件的包名
* 2、这样交给外界的时候,其ComponentName已变成“插件名-类名”的形式,可以做下一步处理
* 3、若其后处理失败,则仍会调用系统的相应方法(但不是该函数的职责)
*
* @param c 根据Context内容来决定如何填充Intent,此为那个Context对象
* @param from ComponentName
* @return 新的ComponentName。或者如果插件有问题,则返回from
*/
public static ComponentName getComponentNameByContext(Context c, ComponentName from) {
if (from == null) {
// 如果Intent里面没有带ComponentName,则我们不支持此特性,直接返回null
// 外界会直接调用其系统的对应方法
return null;
}
String appPackage = IPC.getPackageName();
if (!TextUtils.equals(from.getPackageName(), appPackage)) {
// 自己已填好了要使用的插件名(作为CN的Key),这里不做处理
return from;
}
// 根据Context的ClassLoader来看到底属于哪个插件,还是只是主程序
ClassLoader cl = c.getClassLoader();
String pn = PluginFactory.fetchPluginName(cl);
if (TextUtils.isEmpty(pn)) {
// 获得了无效的插件信息,这种情况很少见,故打出错误信息,什么也不做
if (LOGR) {
LogRelease.e(PLUGIN_TAG, "pch.iibc: pn is n. n=" + from);
}
} else if (TextUtils.equals(pn, RePlugin.PLUGIN_NAME_MAIN)) {
// 此Context属于主工程,则也什么都不做。稍后会直接走“主程序的Context”来做处理
if (LOG) {
LogDebug.d(PLUGIN_TAG, "PluginClientHelper.iibc(): Call Main! n=" + from);
}
} else {
// 将Context所在的插件名写入CN中,待后面的方法去处理
if (LOG) {
LogDebug.d(PLUGIN_TAG, "PluginClientHelper.iibc(): Call Plugin! n=" + from);
}
return new ComponentName(pn, from.getClassName());
}
return from;
}
private static void injectAboveEqualApiLevel14(Context context, String str, String str2)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
Object a = combineArray(getDexElements(getPathList(pathClassLoader)),
getDexElements(getPathList(
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader()))));
Object a2 = getPathList(pathClassLoader);
setField(a2, a2.getClass(), "dexElements", a);
pathClassLoader.loadClass(str2);
}
private static void doDexInject(Context appContext, HashSet<File> loadedDex) {
String optimizeDir = appContext.getFilesDir().getAbsolutePath() + File.separator + OPTIMIZE_DEX_DIR;// data/data/包名/files/optimize_dex(这个必须是自己程序下的目录)
File fopt = new File(optimizeDir);
if (!fopt.exists()) {
fopt.mkdirs();
}
try {
// 1.加载应用程序的dex
PathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader();
for (File dex : loadedDex) {
// 2.加载指定的修复的dex文件
DexClassLoader dexLoader = new DexClassLoader(
dex.getAbsolutePath(),// 修复好的dex(补丁)所在目录
fopt.getAbsolutePath(),// 存放dex的解压目录(用于jar、zip、apk格式的补丁)
null,// 加载dex时需要的库
pathLoader// 父类加载器
);
// 3.合并
Object dexPathList = getPathList(dexLoader);
Object pathPathList = getPathList(pathLoader);
Object leftDexElements = getDexElements(dexPathList);
Object rightDexElements = getDexElements(pathPathList);
// 合并完成
Object dexElements = combineArray(leftDexElements, rightDexElements);
// 重写给PathList里面的Element[] dexElements;赋值
Object pathList = getPathList(pathLoader);
setField(pathList, pathList.getClass(), "dexElements", dexElements);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getProp(Context context, String property) {
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
@SuppressWarnings("unchecked")
Method method = SystemProperties.getMethod("get", String.class);
Object[] params = new Object[1];
params[0] = new String(property);
return (String)method.invoke(SystemProperties, params);
} catch (Exception e) {
return null;
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// 如果当前 ClassLoader 与 context 的 classLoader 不一致,则为宿主运行
mInHost = getClass().getClassLoader() != context.getClassLoader();
if (mInHost) {
initPackageName();
modifyHostContextForPlugin();
}
}
public static ClassLoader createClassLoader(String name) {
Context context = ApplicationContextHolder.getContext();
File extractFile = context.getFileStreamPath(name);
String dexPath = extractFile.getPath();
String libPath = PluginUtils.unzipLibraryFile(dexPath, extractFile.getParent());
File fileRelease = context.getDir("dex", Context.MODE_PRIVATE);
return new DexClassLoader(dexPath, fileRelease.getAbsolutePath(), libPath, context.getClassLoader());
}
@TargetApi(14)
private static void injectBelowApiLevel14(Context context, String str) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader(str, context.getDir(Constant.JAR_IN_FOLDER_NAME, 0).getAbsolutePath(), str, context.getClassLoader());
setField(obj, PathClassLoader.class, "mPaths", appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class, "mRawDexPath")));
setField(obj, PathClassLoader.class, "mFiles", combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class, "mFiles")));
setField(obj, PathClassLoader.class, "mZips", combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class, "mZips")));
setField(obj, PathClassLoader.class, "mDexs", combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class, "mDexs")));
}
public ClassLoader getClassLoader(ApplicationInfo appInfo) {
Context context = createPackageContext(appInfo.packageName);
return context.getClassLoader();
}
private ViewProxyBuilder(Context context, Class<T> clazz) {
mContext = context;
mBaseClass = clazz;
mParentClassLoader = context.getClassLoader();
}
private ClassLoader getClassLoader(Context context, String name, String prefix) {
return context.getClassLoader();
}
public static void LoadApplication (Context context, ApplicationInfo runtimePackage, String[] apks)
{
synchronized (lock) {
if (context instanceof android.app.Application) {
Context = context;
}
if (!initialized) {
android.content.IntentFilter timezoneChangedFilter = new android.content.IntentFilter (
android.content.Intent.ACTION_TIMEZONE_CHANGED
);
context.registerReceiver (new mono.android.app.NotifyTimeZoneChanges (), timezoneChangedFilter);
System.loadLibrary("monodroid");
Locale locale = Locale.getDefault ();
String language = locale.getLanguage () + "-" + locale.getCountry ();
String filesDir = context.getFilesDir ().getAbsolutePath ();
String cacheDir = context.getCacheDir ().getAbsolutePath ();
String dataDir = getNativeLibraryPath (context);
ClassLoader loader = context.getClassLoader ();
Runtime.init (
language,
apks,
getNativeLibraryPath (runtimePackage),
new String[]{
filesDir,
cacheDir,
dataDir,
},
loader,
new java.io.File (
android.os.Environment.getExternalStorageDirectory (),
"Android/data/" + context.getPackageName () + "/files/.__override__").getAbsolutePath (),
MonoPackageManager_Resources.Assemblies,
context.getPackageName ());
mono.android.app.ApplicationRegistration.registerApplications ();
initialized = true;
}
}
}