dynamic-load-apk-Apk动态加载框架使用初体验
因为想要将本网站上的开源代码直接做成一个能显示效果的app,决定摸索下android的插件开发,发现只有两个开源的插件系统可选:
因为第一个只允许在fragment的基础上开发插件,第二个没有此限制并且是国人开发,文档比较齐全,所以选择了第二个。
下载dynamic-load-apk
dynamic-load-apk 简称DL框架,从github上下载DL,如下:
lib是Library,sample是例子程序,打开sample如下:
根据官方的解释,有三种模式,其中main目录下才是其推荐的独立插件模式,所以直接不管depend_on_interface这个文件夹了。
其中main-host是宿主,他需要引用DL的Library才能运行,main-plugin-a,以及main-plugin-b是插件。
运行sample中的宿主和插件
我将main直接import到eclispe中,并且将DL的Library也导入,将main-host添加Library依赖,运行main-host程序,当然了 显示的是没有插件,因为main-host程序需要在sdcard的根目录下建立DynamicLoadHost目录,然后DynamicLoadHost目录中放入插件的apk。这主要是因为main-host程序的代码是这样写的:
private void initData() { String pluginFolder = Environment.getExternalStorageDirectory() + "/DynamicLoadHost"; File file = new File(pluginFolder); File[] plugins = file.listFiles(); if (plugins == null || plugins.length == 0) { mNoPluginTextView.setVisibility(View.VISIBLE); return; } for (File plugin : plugins) { PluginItem item = new PluginItem(); item.pluginPath = plugin.getAbsolutePath(); item.packageInfo = DLUtils.getPackageInfo(this, item.pluginPath); if (item.packageInfo.activities != null && item.packageInfo.activities.length > 0) { item.launcherActivityName = item.packageInfo.activities[0].name; } mPluginItems.add(item); DLPluginManager.getInstance(this).loadApk(item.pluginPath); } mListView.setAdapter(mPluginAdapter); mListView.setOnItemClickListener(this); mPluginAdapter.notifyDataSetChanged(); }
pluginFolder
指定为DynamicLoadHost。
当然你自己写的宿主程序完全可以指定为其他目录,甚至直接来源于网上(只是猜想),如果不支持直接加载远程的apk,我们可以先从网上下载下来,放到我们程序指定的一个目录。
接着我们再运行main-plugin-a,产生一个apk放到刚刚在sdcard建立的DynamicLoadHost目录。
然后再次打开宿主程序,点击这个插件,和预期是一致的,插件就像一个apk一样执行了。
尝试自己的apk
虽然官方文档已经说明插件apk需要满足一些要求(context不能用this,jar不能打包在apk中(主要是DL的jar以及surport的jar)等),但是我还是忍不住要尝试一下直接把我的apk放进sdcard的DynamicLoadHost目录,运行宿主程序,列表中能看到我的apk程序,点击,没反应。。。。。。。。。
虽然在意料之中,但是小心脏还是小小的失落。
先说下我运行的这个程序叫GossipView,在github上可以下载,因为GossipView非常简单且具有代表性,没有依赖其他库(GossipView是直接在demo中一起的),有activity,有一个自定义的GossipView。对于我准备开发的东西来说,如果这个东西都不能运行,那就没什么意义了。
我开始改造我的GossipView,让他可以作为插件了:增加了external-jars 将DL的jar放进去,并且将surport的jar也放进去,同时在.classpath中追加如下两句:
<classpathentry kind="lib" path="external-jars/dl-lib.jar"/>
<classpathentry kind="lib" path="external-jars/android-support-v4.jar"/>
这样,编译的时候就能够正常进行,但是打包的时候,就不会把上面两个jar包打入到插件apk中。
接下来不是要改this为that吗,改呗,我发现我的activity中只有一处用了this,替换成that,运行。得到了一个apk,但是很奇怪的是我的插件居然能直接运行,不是说那样做两个jar不会被打包进去吗怎么还能运行了呢。。。。
管他的哦,先将这次的apk放进去再说。
运行宿主,点开我的插件,报错了:
看来还真的是包多了,也就是说我的插件apk中其实把DL和surport的jar打包进去了。
我找啊找啊找,发现是自己粗心了,我在插件项目中添加了两次DL,一次是用jar,一次是直接添加了Library的依赖。fuck。
好吧改过来之后,完全可以了,只是原本我应用的白色背景变成了黑色背景。