深入理解Android插件化技术

  • 时间:
  • 浏览:0
  • 来源:uu快3计划_uu快3官方_单双

四大组件中Activity的支持是最复杂的,有些组件的实现原理要简单有些有些,简要概括如下:

上图列出的是启动一三个白多 Activity的主要过程,具体步骤如下:

还可以 看出ClassLoader加载类时,先查看自身是不是 意味 加载过该类,意味 这样加载过会首先让父加载器去加载,意味 父加载器无法加载该类时才会调用自身的findClass措施加载,该机制很大程度上出理 了类的重复加载。

上述代码是在Activity创建时被调用的(上方会介绍怎样才能hook Activity的创建过程),在activity被构创造创造发明来后,还可以 了替换其中的mResources为插件的Resource。意味 独立式时主工程的Resource还可以 了访问插件的资源,有些有些意味 不做替换,会产生资源访问错误。

DexPathList的loadClass会去遍历DexFile直到找到还可以 了加载的类。

VirtualAPK通过替换了系统的Instrumentation,hook了Activity的启动和创建,省去了手动管理插件Activity生命周期的繁琐,让插件Activity像正常的Activity一样被系统管理,已经 插件Activity在开发时和常规一样,即能独立运行又能作为插件被主工程调用。

资源id是由8位16进制数表示,表示为0xPPTTNNNN。PP段用来区分包空间,默认只区分了应用资源和系统资源,TT段为资源类型,NNNN段在同一三个白多 APK中从0000递增。如下表所示:

通常让我们 通过Context对象访问资源,光创建出Resource对象还严重不足,已经 还还可以 了有些额外的工作。 对资源访问的不同实现措施也还可以 了不同的额外工作。以VirtualAPK的出理 措施为例。

第一步:创建Resource

对于单DexClassLoader来说,其模型如下:



将插件的DexClassLoader中的pathList合并到主工程的DexClassLoader中。曾经做的好处时,还可以 在不同的插件以及主工程间直接互相调用类和措施,已经 还可以 将不同插件的公共模块抽出来中放一三个白多 common插件中直接供有些插件使用。Small采用的是你这一措施。

还可以 说,插件化技术涉及得非常广泛,其中最核心的已经 Android的类加载机制和反射机制,相关原理请让我们 自行百度。

合并式意味 AssetManager中加入了所有插件和主工程的路径,已经 生成的Resource还可以 一起访问插件和主工程的资源。但意味 主工程和各个插件也有独立编译的,生成的资源id会指在相同的清况 ,在访问也有产生资源冲突。

已经 ,假如将插件apk的路径加入到AssetManager中,便还可以实现对插件资源的访问。

VAInstrumentation类重写了execStartActivity措施,相关代码如下:

有些插件框架在出理 Activity时思想大都差太少,无非是这有本身措施之一意味 两者的结合。在hook时,不同的框架意味 会选泽不同的hook点。如31000的RePlugin框架选泽hook了系统的ClassLoader,即图3.2中构造Activity2的ClassLoader,在判断出待启动的Activity是插件中的时,会调用插件的ClassLoader构造相应对象。另外RePlugin为了系统稳定性,选泽了尽量少的hook,已经 它并这样选泽hook系统的startActivity措施来替换intent,已经 通过重写Activity的startActivity,已经 其插件Activity是还可以 了继承一三个白多 相似PluginActivity的基类的。不过RePlugin提供了一三个白多 Gradle插件将插件中的Activity的基类加在了PluginActivity,用户在开发插件Activity时也是这样感知的。

插件化技术最初源于免安装运行apk的想法,你这一免安装的apk还可以 理解为插件。支持插件化的app还可以 在运行时加载和运行插件,曾经便还可以 将app带有些不常用的功能模块做成插件,一方面减小了安装包的大小,当时人面还可以 实现app功能的动态扩展。不让实现插件化,主已经 出理 下面三个白多 那些的问題:

缺点

做完以上工作后,则还可以 在插件的Activity中放心的使用setContentView,inflater等措施加载布局了。

这里要重点说一下DexClassLoader的DexPathList。DexClassLoader重载了findClass措施,在加载类也有调用其内内外部的DexPathList去加载。DexPathList是在构造DexClassLoader时生成的,其内内外部带有了DexFile。如下图所示:

下面是比较出名的几次开源的插件化框架,按照出显 的时间排序。研究它们的实现原理,还可以 大致看出插件化技术的发展,根据实现原理还可以 将这几次框架划分成了三代。

该措施觉得还可以很好的实现启动插件Activity的目的,但意味 开发式侵入性很强,dynamic-load-apk过后的插件化方案很少继续使用该措施,已经 通过hook系统启动Activity的过程,让启动插件中的Activity像启动主工程的Activity一样简单。

Android系统通过Resource对象加载资源,下面代码展示了该对象的生成过程。

ClassLoader调用loadClass措施加载类,代码如下:

上一步欺骗了系统,让系统以为当时人启动的是一三个白多 正常的Activity。当来到图 3.2的第10步时,再将插件的Activity换回来。此时调用的是VAInstrumentation类的newActivity措施。

通过给插件apk生成相应的DexClassLoader便还可以 访问其中的类,这边又有有本身出理 措施,有单DexClassLoader和多DexClassLoader有本身内外部。

对于多DexClassLoader内外部来说,还可以 用下面的模型来标识。



对于每个插件也有生成一三个白多 DexClassLoader,当加载该插件中的类时还可以 了通过对应DexClassLoader加载。曾经不同插件的类是隔离的,当不同插件引用了同一三个白多 类库的不同版本时,不让出那些的问題,RePlugin采用的已经 此方案。

插件和主工程的互相调用涉及到以下三个白多 那些的问題:

插件调用主工程在构造插件的ClassLoader也有传入主工程的ClassLoader作为父加载器,有些有些插件是还可以 直接还可以 通过类名引用主工程的类。

Android开发带有有些特殊的类,是由系统创建的,已经 由系统管理生命周期。如常用的四大组件,Activity,Service,BroadcastReceiver和ContentProvider。 仅仅构创造创造发明那些类的实例是没用的,还还可以 了管理组件的生命周期。其中以Activity最为复杂,不同框架采用的措施已经 尽相同。下面以Activity为例全部介绍插件化怎样才能支持组件生命周期的管理。 大致分为有本身措施:

经过上述步骤后,便实现了插件Activity的启动,已经 该插件Activity中不让还可以 了那些额外的出理 ,和常规的Activity一样。那那些的问題来了,过后的onResume,onStop等生命周期为什么在么在办呢?答案是所有和Activity相关的生命周期函数,系统也有调用插件中的Activity。意味 在于AMS在出理 Activity时,通过一三个白多 token表示具体Activity对象,而你这一token正是和启动Activity时创建的对象对应的,而你这一Activity被让我们 替加在了插件中的Activity,有些有些过后AMS的所有调用也有传给插件中的Activity。

关于双亲委托更全部的资料,让我们 也还可以 访问我博客过后的介绍:classloader双亲委托模式

和代码加载相似,插件和主工程的资源关系也有有本身出理 措施:

execStartActivity中会先去出理 隐式intent,意味 该隐式intent匹配到了插件中的Activity,将其转加在显式。过后通过markIntentIfNeeded将待启动的的插件Activity替加在了预先在AndroidManifest中占坑的StubActivity,并将插件Activity的信息保存到该intent中。其带有个dispatchStubActivity函数,会根据Activity的launchMode选泽具体启动哪个StubActivity。VirtualAPK为了支持Activity的launchMode在主工程的AndroidManifest中对于每段启动模式的Activity都预埋了多个坑位。

区别在于调用父类构造器时,DexClassLoader多传了一三个白多 optimizedDirectory参数,你这一目录还可以 了是内内外部存储路径,用来缓存系统创建的Dex文件。而PathClassLoader该参数为null,还可以 了加载内内外部存储目录的Dex文件。有些有些让我们 还可以 用DexClassLoader去加载内外部的apk,用法如下:

下面介绍怎样才能通过hook的措施启动插件中的Activity,还可以 了出理 以下三个白多 那些的问題:

ProxyActivity代理的措施最早是由dynamic-load-apk提出的,其思想很简单,在主工程中放一三个白多 ProxyActivy,启动插件中的Activity也有先启动ProxyActivity,在ProxyActivity中创建插件Activity,并同步生命周期。下图展示了启动插件Activity的过程。



具体的过程如下:

意味 AndroidManifest中预埋的StubActivity并这样具体的实现类,有些有些此也有指在ClassNotFoundException。过后在出理 异常时取出插件Activity的信息,通过插件的ClassLoader反射构造插件的Activity。

理解ProxyActivity代理措施主要注意两点:

具体实现时,意味 AssetManager并也有一三个白多 public的类,还可以 了通过反射去创建,已经 每段Rom对创建的Resource类进行了修改,有些有些还可以 了考虑不同Rom的兼容性。

VirtualAPK在初始化也有调用hookInstrumentationAndHandler,该措施hook了系统的Instrumentaiton类,由上文可知该类和Activity的启动息息相关。

独立式时,各个插件的资源是互相隔离的,不过意味 不让实现资源的共享,还可以 了拿到对应的Resource对象。

插件化技术还可以 说是Android高级工程师所还可以 了具备的技能之一,从2012年插件化概念的提出(Android版本),到2016年插件化的百花争艳,还可以 说,插件化技术引领着Android技术的进步。本篇文章转载自腾讯bugly,觉得写得不错,转载分享给让我们 。

第二步:hook主工程的Resource

对于合并式的资源访问措施,还可以 了替换主工程的Resource,下面是具体替换的代码。

合并式的资源出理 措施,会引入资源冲突,意味 在于不同插件中的资源id意味 相同,有些有些出理 措施已经 使得不同的插件资源拥有不同的资源id。

第一代:dynamic-load-apk最早使用ProxyActivity你这一静态代理技术,由ProxyActivity去控制插件中PluginActivity的生命周期。该种措施缺点明显,插件中的activity还可以 了继承PluginActivity,开发还可以 了小心出理 context。而DroidPlugin通过Hook系统服务的措施启动插件中的Activity,使得开发插件的过程和开发普通的app这样那些区别,但意味 hook太少系统服务,异常复杂且严重不足稳定。

第二代:为了一起达到插件开发的低侵入性(像开发普通app一样开发插件)和框架的稳定性,在实现原理上也有趋近于选泽尽量少的hook,并通过在manifest中预埋有些组件实现对四大组件的插件化。另外各个框架根据其设计思想都做了不同程度的扩展,其中Small更是做成了一三个白多 跨平台,组件化的开发框架。

第三代:VirtualApp比较厉害,还可以全部模拟app的运行环境,还可以实现app的免安装运行和双开技术。Atlas是阿里今年开源出来的一三个白多 结合组件化和热修复技术的一三个白多 app基础框架,其广泛的应用与阿里系的各个app,其号称是一三个白多 容器化框架。

觉得,关于类加载更全部的内容,笔者也深入剖析过,还可以 查看下面的链接:类加载机制详解

插件Activity构创造创造发明来后,为了还可以保证其正常运行还可以 了做些额外的工作。

注意下上述代码hook了几次地方,包括以下几次hook点:

替换了主工程context中LoadedApk的mResource对象。

将新的Resource加在到主工程ActivityThread的mResourceManager中,已经 根据Android版本做了不同出理 。

第三步:关联resource和Activity

Android中常用的有有本身类加载器,DexClassLoader和PathClassLoader,它们都继承于BaseDexClassLoader。相关源码如下:

有些有些思路是修改资源ID的PP段,对于不同的插件使用不同的PP段,从而区分不同插件的资源。具体实现措施有有本身:

在介绍hook措施过后,先用一张图简要的介绍下系统是怎样才能启动一三个白多 Activity的。

出理 措施有有些有些种,以VirtualAPK为例,核心思路如下:

这段代码主已经 将Activity中的Resource,Context等对象替加在了插件的相应对象,保证插件Activity在调用涉及到Context的措施时还可以正确运行。

腾讯的qq空间热修复技术正是利用了DexClassLoader的加载机制,将还可以 了替换的类加在到dexElements的前面,曾经系统会使用先找到的修复过的类。

该段代码将主程序运行运行中的Instrumentation对象替加在了自定义的VAInstrumentation类。在启动和创建插件activity时,该类也有偷偷做有些手脚。