private static void callPluginApplicationOnCreate(PluginDescriptor pluginDescriptor) { Application application = null; if (pluginDescriptor.getPluginApplication() == null && pluginDescriptor.getPluginClassLoader() != null) { try { LogUtil.d("创建插件Application", pluginDescriptor.getApplicationName()); application = Instrumentation.newApplication( pluginDescriptor .getPluginClassLoader() .loadClass(pluginDescriptor.getApplicationName()), pluginDescriptor.getPluginContext()); pluginDescriptor.setPluginApplication(application); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } // 安装ContentProvider PluginInjector.installContentProviders( sApplication, pluginDescriptor.getProviderInfos().values()); // 执行onCreate if (application != null) { application.onCreate(); } changeListener.onPluginStarted(pluginDescriptor.getPackageName()); }
@SuppressWarnings("rawtypes") public static Class loadPluginClassByName(String clazzName) { PluginDescriptor pluginDescriptor = getPluginDescriptorByClassName(clazzName); if (pluginDescriptor != null) { ensurePluginInited(pluginDescriptor); DexClassLoader pluginClassLoader = pluginDescriptor.getPluginClassLoader(); try { Class pluginClazz = ((ClassLoader) pluginClassLoader).loadClass(clazzName); LogUtil.d("loadPluginClass Success for clazzName ", clazzName); return pluginClazz; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (java.lang.IllegalAccessError illegalAccessError) { illegalAccessError.printStackTrace(); throw new IllegalAccessError( "出现这个异常最大的可能是插件dex和" + "宿主dex包含了相同的class导致冲突, " + "请检查插件的编译脚本,确保排除了所有公共依赖库的jar"); } } LogUtil.e("loadPluginClass Fail for clazzName ", clazzName); return null; }
/** * 根据插件中的classId加载一个插件中的class * * @param clazzId * @return */ @SuppressWarnings("rawtypes") public static Class loadPluginFragmentClassById(String clazzId) { PluginDescriptor pluginDescriptor = getPluginDescriptorByFragmenetId(clazzId); if (pluginDescriptor != null) { ensurePluginInited(pluginDescriptor); DexClassLoader pluginClassLoader = pluginDescriptor.getPluginClassLoader(); String clazzName = pluginDescriptor.getPluginClassNameById(clazzId); if (clazzName != null) { try { Class pluginClazz = ((ClassLoader) pluginClassLoader).loadClass(clazzName); LogUtil.d("loadPluginClass for clazzId", clazzId, "clazzName", clazzName, "success"); return pluginClazz; } catch (ClassNotFoundException e) { e.printStackTrace(); } } } LogUtil.e("loadPluginClass for clazzId", clazzId, "fail"); return null; }
/** * 构造插件信息 * * @param */ static void ensurePluginInited(PluginDescriptor pluginDescriptor) { if (pluginDescriptor != null) { DexClassLoader pluginClassLoader = pluginDescriptor.getPluginClassLoader(); if (pluginClassLoader == null) { LogUtil.d("正在初始化插件Resources, DexClassLoader, Context, Application "); LogUtil.d("是否为独立插件", pluginDescriptor.isStandalone()); Resources pluginRes = PluginCreator.createPluginResource( sApplication, pluginDescriptor.getInstalledPath(), pluginDescriptor.isStandalone()); pluginClassLoader = PluginCreator.createPluginClassLoader( pluginDescriptor.getInstalledPath(), pluginDescriptor.isStandalone()); Context pluginContext = PluginCreator.createPluginApplicationContext( pluginDescriptor, sApplication, pluginRes, pluginClassLoader); pluginContext.setTheme(sApplication.getApplicationContext().getApplicationInfo().theme); pluginDescriptor.setPluginContext(pluginContext); pluginDescriptor.setPluginClassLoader(pluginClassLoader); // 使用了openAtlasExtention之后就不需要Public.xml文件了 // checkPluginPublicXml(pluginDescriptor, pluginRes); callPluginApplicationOnCreate(pluginDescriptor); LogUtil.d("初始化插件" + pluginDescriptor.getPackageName() + "完成"); } } }
@SuppressWarnings("rawtypes") public static Class loadPluginClassByName(String clazzName) { PluginDescriptor pluginDescriptor = getPluginDescriptorByClassName(clazzName); if (pluginDescriptor != null) { ensurePluginInited(pluginDescriptor); DexClassLoader pluginClassLoader = pluginDescriptor.getPluginClassLoader(); try { Class pluginClazz = ((ClassLoader) pluginClassLoader).loadClass(clazzName); LogUtil.d("loadPluginClass Success for clazzName ", clazzName); return pluginClazz; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (java.lang.IllegalAccessError illegalAccessError) { illegalAccessError.printStackTrace(); } } LogUtil.e("loadPluginClass Fail for clazzName ", clazzName); return null; }
/** * 构造插件信息 * * @param */ static void ensurePluginInited(PluginDescriptor pluginDescriptor) { if (pluginDescriptor != null) { DexClassLoader pluginClassLoader = pluginDescriptor.getPluginClassLoader(); if (pluginClassLoader == null) { LogUtil.e( "正在初始化插件" + pluginDescriptor.getPackageName() + "Resources, DexClassLoader, Context, Application"); LogUtil.d("是否为独立插件", pluginDescriptor.isStandalone()); Resources pluginRes = PluginCreator.createPluginResource(sApplication, pluginDescriptor); pluginClassLoader = PluginCreator.createPluginClassLoader( pluginDescriptor.getInstalledPath(), pluginDescriptor.isStandalone(), pluginDescriptor.getDependencies()); Context pluginContext = PluginCreator.createPluginContext( pluginDescriptor, sApplication, pluginRes, pluginClassLoader); // 插件Context默认主题设置为插件application主题 pluginContext.setTheme(pluginDescriptor.getApplicationTheme()); pluginDescriptor.setPluginContext(pluginContext); pluginDescriptor.setPluginClassLoader(pluginClassLoader); try { ActivityThread.installPackageInfo(getApplicatoin(), pluginDescriptor.getPackageName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } callPluginApplicationOnCreate(pluginDescriptor); LogUtil.e("初始化插件" + pluginDescriptor.getPackageName() + "完成"); } } }
/** * for eclipse & ant with public.xml * * <p>unused * * @param pluginDescriptor * @param res * @return */ private static boolean checkPluginPublicXml(PluginDescriptor pluginDescriptor, Resources res) { // "plugin_layout_1"资源id时由public.xml配置的 // 如果没有检测到这个资源,说明编译时没有引入public.xml, // 这里直接抛个异常出去。 // 不同的系统版本获取id的方式不同, // 三星4.x等系统适用 int publicStub = res.getIdentifier("plugin_layout_1", "layout", pluginDescriptor.getPackageName()); if (publicStub == 0) { // 小米5.x等系统适用 publicStub = res.getIdentifier("plugin_layout_1", "layout", sApplication.getPackageName()); } if (publicStub == 0) { try { // 如果以上两种方式都检测失败,最后尝试通过反射检测 Class layoutClass = ((ClassLoader) pluginDescriptor.getPluginClassLoader()) .loadClass(pluginDescriptor.getPackageName() + ".R$layout"); Integer layouId = (Integer) RefInvoker.getFieldObject(null, layoutClass, "plugin_layout_1"); if (layouId != null) { publicStub = layouId; } } catch (ClassNotFoundException e) { e.printStackTrace(); } } if (publicStub == 0) { throw new IllegalStateException( "\n插件工程没有使用public.xml给资源id分组!!!\n" + "插件工程没有使用public.xml给资源id分组!!!\n" + "插件工程没有使用public.xml给资源id分组!!!\n" + "重要的事情讲三遍!!!"); } return true; }