插件化加载未安装APK
来源:互联网 发布:中药的软件 编辑:程序博客网 时间:2024/05/21 19:36
主程序专门开一个PluginActivity,在该Activity里通过dexClassLoader动态加载apk,通过反射的方式向被加载apk的mainActivity里传递PluginAvtivity这个参数,相当于在主程序的PluginActivity里画Apk中Activity的View。
PluginActivity中的核心方法:loadApk
DexClassLoader这个类加载器用来从.jar和.apk类型的文件内部加载classes.dex文件。通过这种方式可以用来执行非安装的程序代码,作为程序的一部分进行运行。这个装载类需要一个程序私有的,可写的文件目录去存放优化后的classes文件。通过Contexct.getDir(String, int)来创建这个目录:File dexOutputDir = context.getDir("dex", 0);
public File getDir(String name, int mode):name目录名称、mode权限,如果传入的目录不存在,系统会创建此目录,路径为"/data/data/程序Package Name/app_name",name就是传入的name。
通过以下代码来获得DexClassLoader。dexPath是需要装载的APK的路径
DexClassLoader localDexClassLoader = new DexClassLoader(dexpath, dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader().getParent());
通过以下代码获得应用信息
PackageInfo pkgInfo = getPackageManager().getPackageArchiveInfo(dexpath,
PackageManager.GET_ACTIVITIES);
if ((pkgInfo.activities != null) && (pkgInfo.activities.length > 0)) { String activityname = pkgInfo.activities[0].name; //获得应用信息里的第一个Activity名 localClass = localDexClassLoader.loadClass(activityname);//通过反射加载类型 mActivityClass = localClass; Constructor localConstructor = localClass.getConstructor(new Class[] {});//获得构造方法 instance = localConstructor.newInstance(new Object[] {}); //创建对象实例 mActivityInstance = instance; Method localMethodSetActivity = localClass.getDeclaredMethod("setActivity", new Class[] { Activity.class }); localMethodSetActivity.setAccessible(true); localMethodSetActivity.invoke(instance, new Object[] { this }); //相当于调用MainActivity里的setActivity方法,把PluginActivity传递了进去
此外,还需要获取未安装apk的资源——getApkResoures方法
反射调用android.content.res.AssetManager类,新建个实例,调用隐藏的方法addAssetPath(String path)将为安装APK文件的添加进去,然后用这个AssetManager来构建出一个Resource实例
try { Class<?> class_AssetManager = Class.forName("android.content.res.AssetManager"); Object assetMag = class_AssetManager.newInstance(); Method method_addAssetPath = class_AssetManager .getDeclaredMethod("addAssetPath", String.class); String path = 路径; String fileName = 文件名; method_addAssetPath.invoke(assetMag, path + fileName); Resources res = context.getResources(); Constructor<?> constructor_Resources = Resources.class .getConstructor(class_AssetManager, res.getDisplayMetrics() .getClass(), res.getConfiguration().getClass()); res = (Resources) constructor_Resources.newInstance(assetMag, res.getDisplayMetrics(), res.getConfiguration());} catch (Exception e) { e.printStackTrace();}
在MainActivity里设一个setResources方法,反射调用它,把getApkResoures方法返回的Resource实例传递进去。
最后反射调用MainActivity的onCreate方法
Method methodonCreate = localClass.getDeclaredMethod("onCreate", new Class[] { Bundle.class });
methodonCreate.setAccessible(true);
methodonCreate.invoke(instance, savedInstanceState);
二,如何更换应用主题时同时同步到插件里去?
插件加载资源时先判断Activity的资源里有没有它,有就调用,没有再调用自己的Resource
- 插件化加载未安装APK
- Android 插件化技术 加载任意未安装apk
- Android 插件化技术 加载任意未安装apk
- 插件化开发—动态加载技术加载已安装和未安装的apk
- 插件化开发—动态加载技术加载已安装和未安装的apk
- 插件化开发—动态加载技术加载已安装和未安装的apk
- 插件化开发—动态加载技术加载已安装和未安装的apk
- 插件化开发—动态加载技术加载已安装和未安装的apk
- 动态化加载未安装的apk
- Android插件化基础之加载未安装的apk资源
- 插件化开发系列之二—动态加载技术加载已安装和未安装的apk
- 动态加载未安装APK
- Android插件化开发之用DexClassLoader加载未安装的APK资源文件来实现app切换背景皮肤
- Android插件化开发---运行未安装apk中的Service
- Android插件化开发---运行未安装apk中的Service
- Android插件化开发,运行未安装apk中的Service
- Android插件技术——(三)加载未安装apk
- Android插件技术——(四)加载未安装apk
- OSI参考模型和TCP/IP参考模型的优缺点
- 8.7 js进阶学习三
- 职场分享:如何让自己的工作充满激情
- POJ 2421 Constructing Roads(Kruskal算法)
- POJ 1637 最大流+欧拉回路
- 插件化加载未安装APK
- 4. 二叉树前序、中序、后序递归遍历算法,二叉树前序非递归遍历算法
- Fedora安装/联网
- eclipse快捷键
- KVO机制的应用
- Javascript中最常用的125个经典技巧
- 100个经典的C算法
- -(void)viewWillAppear:(BOOL)animated,- (void)viewDidLoad 的区别。
- C++之练习题33