写点什么

VirtualAPK 详解和使用,网易云的朋友给我这份 339 页的 Android 面经

用户头像
Android架构
关注
发布于: 23 小时前

[](

)1 介绍

Android 插件化技术是比较热门领域,[VirtualAPK](


) 是滴滴 2017 年 6 月 3 号开源,框架功能完备,支持 Android 四大组件,良好的兼容性,且入侵性较低,作为加载耦合插件方案是较好选择。兼容市面上几乎所有的 Android 手机,这一点已经在滴滴出行客户端中得到验证; 资源方面适配小米、VivoNubia 等,对未知机型采用自适应适配方案;极少的 Binder Hook,目前仅仅hook了两个 BinderAMSIContentProviderhook过程做了充分的兼容性适配;插件运行逻辑和宿主隔离,确保框架的任何问题都不会影响宿主的


[](

)2 VirtualAPK 和主流开源框架的对比


[](

)3 原理

[](

)3.1 基本原理

  • 合并宿主和插件的 ClassLoader

  • 需要注意的是,插件中的类不可以和宿主重复

  • 合并插件和宿主的资源

  • 重设插件资源的 packageId,将插件资源和宿主资源合并

  • 去除插件包对宿主的引用

  • 构建时通过 Gradle 插件去除插件对宿主的代码以及资源的引用


[](

)3.2 四大组件的实现原理

  • Activity

  • 采用宿主 manifest 中占坑的方式来绕过系统校验,然后再加载真正的 activity;

  • Service

  • 动态代理 AMS,拦截 service 相关的请求,将其中转给Service Runtime去处理,Service Runtime会接管系统的所有操作;

  • Receiver

  • 将插件中静态注册的 receiver 重新注册一遍;

  • ContentProvider

  • 动态代理 IContentProvider,拦截 provider 相关的请求,将其中转给Provider Runtime去处理,Provider Runtime会接管系统的所有操作。

  • VirtualAPK 的整体架构图,更详细的内容请大家阅读源码。


[](

)3.3 VirtualAPK 的整体架构图


[](

)3.4 原理分析源码

鸿洋大神写的源码分析(滴滴官网都推荐看鸿洋大神写的)


[滴滴插件化方案 VirtualApk 源码解析](


)


下面这位大神就不知道是谁了(滴滴官网推荐看的)


[VirtualAPK 资源加载机制分析](


)


[](

)4 使用

[](

)4.1 插件和宿主必须 compile 相同的 aar

比如宿主 compile 了如下 aar


compile 'com.didi.virtualapk:core:0.9.0'//滴滴 VirtualAPK 的依赖 compile 'com.alibaba:fastjson:1.2.39'compile'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'


插件工程需要访问宿主 sdk 中的类和资源,那么可以在插件工程中同样 compile sdk 的 aar,如下:


compile 'com.didi.virtualapk:core:0.9.0'//滴滴 VirtualAPK 的依赖 compile 'com.alibaba:fastjson:1.2.39'compile'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'


这样一来,插件工程就可以正常地引用 sdk 了。并且,插件构建的时候会自动将这个 aar 从 apk 中剔除


[](

)4.2 宿主工程

  • 在工程根目录下build.gradle中添加


dependencies {classpath 'com.didi.virtualapk:gradle:0.9.0'}


  • 在 App 的build.gradle中顶部添加


apply plugin: 'com.didi.virtualapk.host'


  • 在 App 的build.gradlecompile 添加


dependencies {compile 'com.didi.virtualapk:core:0.9.0'}


  • 编写 MyApp 继承 Application 重写 attachBaseContext 方法中初始化插件引擎(别忘了在 AndroidManifest.xml 配置 Application)


@Overrideprotected void attachBaseContext(Context context) {super.attachBaseContext(context);PluginManager.getInstance(context).init();}


  • 推荐大家在 Application 启动的时候去加载插件,不然的话,请注意插件的加载时机。 考虑一种情况,如果在一个较晚的时机去加载插件并且去访问插件中的资源,请注意当前的 Context。比如在宿主 Activity(MainActivity)中去加载插件,接着在 MainActivity 去访问插件中的资源(比如 Fragment),需要做一下显示的 hook,否则部分 4.x 的手机会出现资源找不到的情况。


PluginManager pluginManager = PluginManager.getInstance(this);//此处是当查看插件 apk 是否存在,如果存在就去加载(比如修改线上的 bug,把插件 apk 下载到 sdcard 的根目录下取名为 Demo.apk)File apk = new File(Environment.getExternalStorageDirectory(), "Demo.apk");if (apk.exists()) {try {pluginManager.loadPlugin(apk);} catch (Exception e) {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
VirtualAPK 详解和使用,网易云的朋友给我这份339页的Android面经