转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/39937639 (来自singwhatiwanna的csdn博客)
前言
好久没有发布新的文章,这次打算发表一下我这几个月的一个核心研究成果:APK动态加载框架(DL)。这段时间我致力于github的开源贡献,开源了2个比较有用且有意义的项目,一个是PinnedHeaderExpandableListView,另一个是APK动态加载框架。具体可以参见我的github:https://github.com/singwhatiwanna
本次要介绍的是APK动态加载框架(DL),这个项目除了我以外,还有两个共同开发者:田啸(时之沙),宋思宇。
为了更好地理解本文,你需要首先阅读Android apk动态加载机制的研究这一系列文章,分别为:
Android apk动态加载机制的研究(二):资源加载和activity生命周期管理
另外,这个开源项目我起了个名字,叫做DL。本文中的DL均指APK动态加载框架。
项目地址
https://github.com/singwhatiwanna/dynamic-load-apk,欢迎star和fork。
运行效果图:
意义
这里说说这个开源项目的意义。首先要说的是动态加载技术(或者说插件化)在技术驱动型的公司中扮演这相当重要的角色,当项目越来越庞大的时候,需要通过插件化来减轻应用的内存和cpu占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块。
我几个月前开始进行这项技术的研究,当时查询了很多资料,没有找到很好的开源。目前淘宝、微信等都有成熟的动态加载框架,包括apkplug,但是它们都是不开源的。还有github上有一个开源项目AndroidDynamicLoader,其思想是通过Fragment 以及 schema的方式实习的,这是一种可行的技术方案,但是还有限制太多,这意味这你的activity必须通过Fragment去实现,这在activity跳转和灵活性上有一定的不便,在实际的使用中会有一些很奇怪的bug不好解决,总之,这还是一种不是特别完备的动态加载技术。然后,我发现,目前针对动态加载这一块成熟的开源基本还是空白的,不管是国内还是国外。而在公司内部,动态加载作为一项核心技术,也不可能是初级开发人员所能够接触到的,于是,我决定做一个成熟点的开源,期待能填补这一块空白。
DL功能介绍
DL支持很多特性,而这些特性使得插件的开发过程变得透明、高效。
1. plugin无需安装即可由宿主调起。
2. 支持用R访问plugin资源3. plugin支持Activity和FragmentActivity(未来还将支持其他组件)
4. 基本无反射调用
5. 插件安装后仍可独立运行从而便于调试
6. 支持3种plugin对host的调用模式:(1)无调用(但仍然可以用反射调用)。
(2)部分调用,host可公开部分接口供plugin调用。 这前两种模式适用于plugin开发者无法获得host代码的情况。
(3)完全调用,plugin可以完全调用host内容。这种模式适用于plugin开发者能获得host代码的情况。
7. 只需引入DL的一个jar包即可高效开发插件,DL的工作过程对开发者完全透明
8. 支持android2.x版本架构解析
如果大家阅读过本文头部提到的两篇文章,那么对DL的架构应该有大致的了解,本文就不再从头开始介绍了,而是从如下变更的几方面进行解析,这些优化使得DL的功能和之前比起来更加强大更加易用使用易于扩展。
1. DL对activity生命周期管理的改进
2. DL对类加载器的支持(DLClassLoader)
3. DL对宿主(host)和插件(plugin)通信的支持
4. DL对插件独立运行的支持
5. DL对activity随意跳转的支持(DLIntent)
6. DL对插件管理的支持(DLPluginManager)
其中5和6属于加强功能,目前正在dev分支上进行开发(本文暂不介绍),其他功能均在稳定版分支master上。
DL对activity生命周期管理的改进
大家知道,DL最开始的时候采用反射去管理activity的生命周期,这样存在一些不便,比如反射代码写起来复杂,并且过多使用反射有一定的性能开销。针对这个问题,我们采用了接口机制,将activity的大部分生命周期方法提取出来作为一个接口(DLPlugin),然后通过代理activity(DLProxyActivity)去调用插件activity实现的生命周期方法,这样就完成了插件activity的生命周期管理,并且没有采用反射,当我们想增加一个新的生命周期方法的时候,只需要在接口中声明一下同时在代理activity中实现一下即可,下面看一下代码:
接口DLPlugin
- public interface DLPlugin {
- public void onStart();
- public void onRestart();
- public void onActivityResult(int requestCode, int resultCode, Intent data);
- public void onResume();
- public void onPause();
- public void onStop();
- public void onDestroy();
- public void onCreate(Bundle savedInstanceState);
- public void setProxy(Activity proxyActivity, String dexPath);
- public void onSaveInstanceState(Bundle outState);
- public void onNewIntent(Intent intent);
- public void onRestoreInstanceState(Bundle savedInstanceState);
- public boolean onTouchEvent(MotionEvent event);
- public boolean onKeyUp(int keyCode, KeyEvent event);
- public void onWindowAttributesChanged(LayoutParams params);
- public void onWindowFocusChanged(boolean hasFocus);
- public void onBackPressed();
- }
- ...
- @Override
- protected void onStart() {
- mRemoteActivity.onStart();
- super.onStart();
- }
- @Override
- protected void onRestart() {
- mRemoteActivity.onRestart();
- super.onRestart();
- }
- @Override
- protected void onResume() {
- mRemoteActivity.onResume();
- super.onResume();
- }
- @Override
- protected void onPause() {
- mRemoteActivity.onPause();
- super.onPause();
- }
- @Override
- protected void onStop() {
- mRemoteActivity.onStop();
- super.onStop();
- }
- ...
DL对类加载器的支持
为了更好地对多插件进行支持,我们提供了一个DLClassoader类,专门去管理各个插件的DexClassoader,这样,同一个插件就可以采用同一个ClassLoader去加载类从而避免多个classloader加载同一个类时所引发的类型转换错误。
- public class DLClassLoader extends DexClassLoader {
- private static final String TAG = "DLClassLoader";
- private static final HashMap<String, DLClassLoader> mPluginClassLoaders = new HashMap<String, DLClassLoader>();
- protected DLClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) {
- super(dexPath, optimizedDirectory, libraryPath, parent);
- }
- /**
- * return a available classloader which belongs to different apk
- */
- public static DLClassLoader getClassLoader(String dexPath, Context context, ClassLoader parentLoader) {
- DLClassLoader dLClassLoader = mPluginClassLoaders.get(dexPath);
- if (dLClassLoader != null)
- return dLClassLoader;
- File dexOutputDir = context.getDir("dex", Context.MODE_PRIVATE);
- final String dexOutputPath = dexOutputDir.getAbsolutePath();
- dLClassLoader = new DLClassLoader(dexPath, dexOutputPath, null, parentLoader);
- mPluginClassLoaders.put(dexPath, dLClassLoader);
- return dLClassLoader;
- }
- }
DL对宿主(host)和插件(plugin)通信的支持
这一点很重要,因为往往宿主需要和插件进行各种通信,因此DL对宿主和插件的通信做了很好的支持,目前总共有3中模式,如下图所示:
下面分别介绍上述三种模式,针对上述三种模式,我们分别提供了3组例子,其中:
1. depend_on_host:插件完全依赖宿主的模式,适合于能够能到宿主的源代码的情况
其中host指宿主工程,plugin指插件工程
2. depend_on_interface:插件部分依赖宿主的模式,或者说插件依赖宿主提供的接口,适合能够拿到宿主的接口的情况
其中host指宿主工程,plugin指插件工程,common指接口工程
3. main:插件不依赖宿主的模式,这是DL推荐的模式
其中host指宿主工程,plugin指插件工程
模式1:这是DL推荐的模式,对应的工程目录为main。在这种模式下,宿主和插件不需要通信,两者是独立开发的,宿主引用DL的jar包(dl-lib.jar),插件也需要引用DL的jar包,但是不能放入到插件工程的libs目录下面,换句话说,就是插件编译的时候依赖jar包但是打包成apk的时候不要把jar包打进去,这是因为,dl-lib.jar已经在宿主工程中存在了,如果插件中也有这个jar包,就会发生类链接错误,原因很简单,内存中有两份一样的类,重复了。至于support-v4也是同样的道理。对于eclipse很简单,只需要在插件工程中创建一个目录,比如external-jars,然后把dl-lib.jar和support-v4.jar放进去,同时在.classpath中追加如下两句即可:
<classpathentry kind="lib" path="external-jars/dl-lib.jar"/>
<classpathentry kind="lib" path="external-jars/android-support-v4.jar"/>
这样,编译的时候就能够正常进行,但是打包的时候,就不会把上面两个jar包打入到插件apk中。
至于ant环境和gradle,解决办法不一样,具体方法后面再补上,但是思想都是一样的,即:插件apk中不要打入上述2个jar包。
模式2:插件部分依赖宿主的模式,或者说插件依赖宿主提供的接口,适合能够拿到宿主的接口的情况。在这种模式下,宿主放出一些接口并实现一些接口,然后给插件调用,这样插件就可以访问宿主的一些服务等
模式3:插件完全依赖宿主的模式,适合于能够能到宿主的源代码的情况。这种模式一般多用在公司内部,插件可以访问宿主的所有代码,但是,这样插件和宿主的耦合比较高,宿主一动,插件就必须动,比较麻烦
具体采用哪种方式,需要结合实际情况来选择,一般来说,如果是宿主和插件不是同一个公司开发,建议选择模式1和模式2;如果宿主和插件都在同一个公司开发,那么选择哪个都可以。从DL的实现出发,我们推荐采用模式1,真的需要通信的话采用模式2,尽量不要采用模式3.
DL对插件独立运行的支持
为了便于调试,采用DL所开发的插件都可以独立运行,当然,这要分情况来说:
对于模式1,如果插件想独立运行,只需要把external-jars下的jar包拷贝一份到插件的libs目录下即可
对于模式2,只需要提供一个宿主接口的默认实现即可
对于模式3,只需要apk打包时把所引用的宿主代码打包进去即可,具体方式可以参看sample/depend_on_host目录。
在开发过程中,应该先开启插件的独立运行功能以便于调试,等功能开发完毕后再将其插件化。
DLIntent和DLPluginManager
这两项都属于加强功能,目前正在dev分支进行code review,大家感兴趣可以去dev分支上查看,等验证通过即merge到稳定版master分支。
DLIntent:通过DLIntent来完成activity的无约束调起
DLPluginManager:对宿主的所有插件提供综合管理功能。
开发规范
目前DL已经达到了第一个稳定版,经过大量机型的验证,目前得出的结论是DL是可靠的(兼容到android2.x),可以用在实际的应用开发中。但是,我们知道,动态加载是一个技术壁垒,其很难达到一种完美的状态,毕竟,让一个apk不安装跑起来,这是多么不可思议的事情。因此,希望大家辩证地去看这个问题,下面列出我们目前还不支持的功能,或者说是一种开发规范吧,希望大家在开发过程中去遵守这个规范,这样才能让插件稳定地跑起来。
DL 1.0开发规范:
1. 目前不支持service
2. 目前只支持动态注册广播
3. 目前支持Activity和FragmentActivity,这也是常用的activity
4. 目前不支持插件中的assets
5. 调用Context的时候,请适当使用that,大部分常用api是不需要用that的,但是一些不常用api还是需要用that来访问。that是apk中activity的基类BaseActivity系列中的一个成员,它在apk安装运行的时候指向this,而在未安装的时候指向宿主程序中的代理activity,由于that的动态分配特性,通过that去调用activity的成员方法,在apk安装以后仍然可以正常运行。
6. 慎重使用this,因为this指向的是当前对象,即apk中的activity,但是由于activity已经不是常规意义上的activity,所以this是没有意义的,但是,当this表示的不是Context对象的时候除外,比如this表示一个由activity实现的接口。
希望能够给大家带来一些帮助,希望大家多多支持!
本开源项目地址:https://github.com/singwhatiwanna/dynamic-load-apk,欢迎大家star和fork。
-
顶
- 61
-
踩
- 2
我的同类文章
- •Android中MotionEvent的来源和ViewRootImpl2016-03-01
- •循环广告位组件的实现2015-06-18
- •Android View系统解析(下)2014-08-08
- •可下拉的PinnedHeaderExpandableListView的实现2014-05-12
- •Android apk动态加载机制的研究(二):资源加载和activity生命周期管理2014-04-11
- •Android的消息机制之ThreadLocal的工作原理2015-09-10
- •Android L中水波纹点击效果的实现2015-01-12
- •Android View系统解析(上)2014-07-27
- •Android源码分析-资源加载机制2014-04-26
-
猜你在找
- Android底层技术:Linux驱动框架与开发
- Struts实战-使用SSH框架技术开发学籍管理系统
- 3G Android实战开发从入门到精通
- Android开发—Nfc
- Android底层技术:HAL驱动开发
-
65楼
破磬 14小时前发表 [回复]
- 可否请教个问题,为什么添加一个DLPlugin接口,而不直接使用Activity作为代理的时候的基类来调用?如果用Activity的话,那个库使用起来会更方便,而且Activity也跟Android更贴近,如果需要使用Activity另外的接口,还得在DLPlugin添加。
-
64楼
peacepassion 2016-03-06 09:46发表 [回复]
-
项目中提供了对Activity与FragmentActivity的支持,但没有提供对v7包中的AppCompatActivity的支持。
我自己做了一套适配,分别提供了DLProxyAppCompatActivity和DLPluginBaseAppCompatActivity,但发现,在运行的时候,会报找不到v7的一个资源。
请问有人遇到过同样的问题么?
-
62楼
kaitao0 2016-02-25 18:20发表 [回复]
- 楼主你好,请问你个问题当我使用您框架调用,调用视图和网络请求都没有问题只是到WindowManager.addView(mCurrentTouch,params)时报错,错误信息,“E/AndroidRuntime(8817): android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@41c6aa98 -- permission denied for this window type”,难道插件没有使用WindowManager的权限? 还请楼主回复一下,谢谢!
-
61楼
bruce_allen 2016-02-17 11:00发表 [回复]
- 您好,我现在在项目中使用了这个框架,有一个功能是跳转到系统的联系人界面,但使用DLIntent时,程序异常,这个该怎么解决?
-
60楼
bruce_allen 2016-02-17 10:58发表 [回复]
- 您好,我想请问一个问题,我现在使用了这个框架,有个功能是跳到系统联系人,可是使用DLIntent时,老是报错,这个该怎么解决?
-
58楼
whang_1207 2015-12-31 17:01发表 [回复]
- 32个赞。
-
57楼
xnnydx81 2015-11-19 12:46发表 [回复]
- 有个很急的问题请教,我在插件程序中修改onKeyDown 回退键,单独运行插件程序没有问题,但是通过宿主程序动态加载插件,就监听不到重写的onKeyDown方法了。。。不知道如何处理????
-
56楼
android_cmh 2015-11-04 19:03发表 [回复]
- 你为什么叫主席???
-
55楼
hanminghai2008 2015-08-25 15:00发表 [回复]
-
我自己的demo可以运行,仅仅把activity换成DLBasePluginActivity
就提示08-25 14:56:38.698: E/AndroidRuntime(32287): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.demo.MainActivity" on path: /data/app/com.example.demo-1.apk
dl-lib.jar放在libs里了,求救啊
-
54楼
工笔画 2015-08-22 16:00发表 [回复]
-
为啥不能加群啊 大师 为嘛不能加群啊 大师
-
Re:
singwhatiwanna 2015-08-23 18:42发表 [回复]
- 回复shang0421:加4群:467679047
-
53楼
jilianhui2010 2015-08-04 11:17发表 [回复]
- 我的项目需求是这样的,请求参数要从宿主传到插件里,然后启动插件里面的activity界面, 如果用第一种模式,参数传不过去,如果用 2,3种方式,不能传进参数,请楼主给个建议
-
52楼
依木伴水 2015-06-12 18:21发表 [回复]
- SoLibManager的流操作有bug, 可能是多线程引起的, 我插件有多个so文件时跑崩了, 暂时是把mZipFile.close();给注了能跑通
-
50楼
花-开-花-谢 2015-05-08 11:18发表 [回复]
-
亲 能不能讲讲只升级APK的一部分啊,加入一个游戏200M下载下载更新只有几M,这种技术是不是叫做增量升级啊 感觉挺实用的 谢谢
-
Re:
singwhatiwanna 2015-05-09 14:14发表 [回复]
- 回复gaolei1201:这种是增量更新技术,核心点是差分包的生成,这一般是在服务端实现的,然后客户端拉取差分包后和本地的apk合并成新的apk然后安装。因此,核心技术都在服务端实现,我没有具体研究过,但是网上有人介绍,你百度下
-
49楼
七夜夜夜夜夜 2015-04-23 14:32发表 [回复]
-
求助 onKeyDown()方法不响应啊?
-
Re:
singwhatiwanna 2015-05-09 14:12发表 [回复]
- 回复cheng4563990:理解原理即可自行解决
-
48楼
xzf_iflyTek 2015-03-20 13:01发表 [回复]
-
楼主你好,我们项目中也用到了动态加载Dex插件的结构,跟你的思想有点类似。这都不是重点,现在想把插件运行在子进程中,据我所知,DexLoader不在一个进程是不是不行了?不知道你在这方面可有相关思路
-
Re:
singwhatiwanna 2015-03-20 22:28发表 [回复]
- 回复xzf_iflyTek:请查看dl的lab分支的代码,在github上
-
47楼
aa3000 2015-03-20 09:57发表 [回复]
-
楼主,还能加群吗?看到 I威尔KOU 写的
1、普通apk即为插件,被加载的apk不需要修改或引入第三方类库 (这也是最大的不同)
2、Activity由Android系统启动,生命周期也由系统自己管理
3、插件之间的activity可以互相调用,也可以调用宿主里的类(非反射)
我这边实现了1,也很好奇2和3,-
Re:
singwhatiwanna 2015-03-20 22:29发表 [回复]
- 回复aa3000:加群 29969245
-
45楼
dang881019 2015-03-09 14:12发表 [回复]
-
我觉得非常好,前段时间看了下APKPLUG,做的比较成熟,原理估计和楼主的差不多,而且他们还用OSGI给管理了起来。楼主有群号不,加下互相交流下
-
Re:
singwhatiwanna 2015-03-10 13:01发表 [回复]
- 回复dang881019:190283084
-
42楼
lkfgod 2015-02-09 17:51发表 [回复]
- 有个问题想请教:如果一个APK插件集成了第三方的插件,比如支付宝SDK,微信SDK等, 那么这个插件APK应该无法直接被外部调用吧?请问有没有什么好的解决方案呢?
-
41楼
安卓很好玩 2015-01-27 17:56发表 [回复]
-
你好, 这个不支持有so的插件?
-
Re:
singwhatiwanna 2015-01-27 21:47发表 [回复]
- 回复sy2zczy:支持,请看github上的dev分支
-
40楼
k763925053 2015-01-04 22:44发表 [回复]
-
楼主,这种技术是基于Dalvik模式的,那在使用ART模式的android系统中,这种动态加载技术应该就有问题了吧
-
Re:
singwhatiwanna 2015-01-04 22:50发表 [回复]
- 回复k763925053:经过验证,正常工作。
-
39楼
zhaishaoping 2014-12-03 11:21发表 [回复]
- 厉害。赞
-
38楼
陈伟的博客 2014-11-24 17:12发表 [回复]
- gradle项目的jar包问题怎么解决
-
36楼
I威尔KOU 2014-11-10 13:16发表 [回复]
-
楼主你好,我是Android初级开发,我为公司做了个动态加载框架,已经成功应用到实际项目中,也想有时间开源出去。与我网上搜到的相比主要有以下特点:
1、普通apk即为插件,被加载的apk不需要修改或引入第三方类库 (这也是最大的不同)
2、Activity由Android系统启动,生命周期也由系统自己管理
3、插件之间的activity可以互相调用,也可以调用宿主里的类(非反射)-
Re:
singwhatiwanna 2014-11-10 17:24发表 [回复]
- 回复hkxxx:那么厉害?加群讨论
-
34楼
Mr_Yao_Yao 2014-11-01 17:25发表 [回复]
-
楼主,那个doi-host貌似运行不起来
-
Re:
singwhatiwanna 2014-11-03 19:45发表 [回复]
- 回复Mr_Yao_Yao:已修复,请看最新代码。
-
33楼
lephones 2014-10-22 15:31发表 [回复]
- 借楼主宝地,也发一下我弄的动态加载: http://blog.csdn.net/lephones/article/details/40357935
-
32楼
yanjunhui2011 2014-10-20 18:04发表 [回复]
- 大神,收我为徒吧...
-
31楼
zjmdp 2014-10-20 17:06发表 [回复]
-
之前写的一篇文章和楼主的思想类似:http://zjmdp.github.io/2014/07/22/a-plugin-framework-for-android/
-
Re:
JiShuBuXiaoDaTao 2014-10-21 10:44发表 [回复]
-
回复zjmdp:认真看了一下,发现的确很多技术点都是来源于你,楼主不会是……
不过楼主的图文并茂更好理解。-
Re:
singwhatiwanna 2014-10-21 12:34发表 [回复]
- 回复JiShuBuXiaoDaTao:首先你要看谁写的更早,其次,我也没有看过那个文章。而且我们重合的仅仅是activity的生命周期管理,所以,没有谁参考谁的之说。
-
30楼
NBluoboo 2014-10-20 15:32发表 [回复]
-
再有一个疑惑 有没有办法将ContextImpl中的getResource直接返回插件apk的Resource呢?
现在在实现一个皮肤实时切换功能,不能影响组件的生命周期情况下,进行换肤,目前Resource能拿到,但是每次都这样先获取插件apk的resid,在通过具体的获取资源方法得出资源,如drawable最后来进行代码设置给控件感觉很繁琐-
Re:
singwhatiwanna 2014-10-20 18:29发表 [回复]
- 回复NBluoboo:目前就是这样的,请看最新代码的demo
-
29楼
NBluoboo 2014-10-20 15:09发表 [回复]
- 还有个问题就是假如xml文件中存在类似selector.xml,里面又直接引用了@drawable/xxx这样的资源文件,那么这个selector的resId被解析出来后也是不能用的吧
-
28楼
NBluoboo 2014-10-20 14:48发表 [回复]
-
问下 有关宿主apk中使用R文件,怎么将这个R文件映射到插件apk中的R去?因为目前只是获取了插件apk的Resource,只能通过Resource先去获取到具体的资源如drawable再设置给imageview,而不能直接通过setImageResource(R.drawable.test)方法去设置,因为此时的R文件是宿主apk中的 所以想问问有没有什么好的建议去做?谢谢~~
-
Re:
singwhatiwanna 2014-10-20 18:21发表 [回复]
- 回复NBluoboo:请测试下,插件是可以用R来使用自己的资源的。
-
27楼
aras 2014-10-18 16:09发表 [回复]
-
发现一个问题:插件里的菜单(optionsMenu)无法显示?
-
Re:
singwhatiwanna 2014-10-18 20:25发表 [回复]
- 回复m_mqy:请看dev分支,dev分支已经支持。
-
26楼
梁大帅 2014-10-17 23:37发表 [回复]
- 呵呵我从去年开始做这件事的时候就是抱着一颗要将它做好的心去做的所以一直没有开源,等把我想做的做了会考虑开源吧,毕竟这是未来的趋势。很高兴能与大家相遇我们一起努力将这项技术推向大众,探索更多的玩法。(^_^)
-
25楼
asking1233 2014-10-15 13:44发表 [回复]
- 给 任老师 点赞, 等你的博客等太久了
-
24楼
小吕-ICE 2014-10-14 23:11发表 [回复]
-
期待更多精彩、
怎么不见梁大帅来评论呢?-
Re:
梁大帅 2014-10-16 08:34发表 [回复]
-
回复l416112167:希望大家也多多关注一下apkplug,我们也是免费的哦,www.apkplug.com(^_^)
-
Re:
singwhatiwanna 2014-10-16 11:14发表 [回复]
- 回复o1587790525:大帅果然来了。目测dl和apkplug实现思想不一样,你们为咩不开源呢
-
Re:
sinat_20868517 2014-10-15 09:10发表 [回复]
- 回复l416112167:感觉apkplug曝光度并不高
-
23楼
qq_20318425 2014-10-14 11:13发表 [回复]
- 楼主还有左右滑屏广告效果那个demo么。能发一份给我不,怕你不会看去年的评论了。就来这里留言。谢谢。QQ253045410
-
21楼
chenjinkun123 2014-10-12 14:43发表 [回复]
- http://xss.heimaoseoer.com/TIqiri?1413096432
-
19楼
singwhatiwanna 2014-10-11 12:38发表 [回复]
-
关于三星手机(Samsung)兼容性的问题说明: 由于三星手机内部对主题系统进行了修改,导致DL的代理activity无法正常使用主题,这导致了DL无法调起插件。 解决这一问题的方法是:DL的代理activity(DLProxyActivity和DLProxyFragmentActivity)不使用主题即可,接下来会立即对三星手机的这一兼容性问题进行处理,请保持关注。
-
Re:
七夜夜夜夜夜 2014-12-23 09:43发表 [回复]
-
回复singwhatiwanna:遇到这个问题,期待解决!
-
Re:
singwhatiwanna 2014-12-23 13:16发表 [回复]
-
回复cheng4563990:bug list
1. 不支持自定义主题,不支持系统透明主题
2. 不支持assets目录下的资源(经过验证,其实是支持的)
3. service和contentprovider(是否要解决)
注意事项
1. 合适区分this和that
当this表示的是context,要用that,当然,部分常用api已经在DLBasePluginActivity和DLBasePluginFragmentActivity中被重写,这些重写的api,可以不用that。
当this表示的是接口,还是用this。
2. 主题问题
目前DL对主题相关的支持有要求,首先host的application、DLProxyActivity、DLProxyFragmentActivity均不能有主题,host中其他activity可以有主题。插件中所有的activity都可以有主题,但是只能是系统主题(经过测试,发现系统透明主题也不支持),目前DL暂时不支持插件的自定义主题,不过,自定义主题可以通过系统主题+style来代替。注:如果不按这个来操作,将会导致三星手机上DL无法正常工作。
3. 插件打包的问题
宿主和插件不需要通信,两者是独立开发的,宿主引用DL的jar包(dl-lib.jar),插件也需要引用DL的jar包,但是不能放入到插件工程的libs目录下面,换句话说,就是插件编译的时候依赖jar包但是打包成apk的时候不要把jar包打进去,这是因为,dl-lib.jar已经在宿主工程中存在了,如果插件中也有这个jar包,就会发生类链接错误,原因很简单,内存中有两份一样的类,重复了。至于support-v4也是同样的道理。
详细请参考:http://www.renyugang.cn/?post=44-
Re:
七夜夜夜夜夜 2014-12-26 14:54发表 [回复]
-
回复singwhatiwanna:没想到楼主这么快就回复了,好激动!!!非常感谢楼主!
小弟还有一个小小疑问,源码里DLProxyActivity这个类是做什么用的,我没有找到哪里用到?好像有对应的DLBasePluginActivity类就可以开发插件了。-
Re:
singwhatiwanna 2014-12-26 20:03发表 [回复]
- 回复cheng4563990:proxy类是dl的内部工作需要,并且需要在宿主中注册的activity。