赞
踩
宿主启动插件activity方式 RePlugin.startActivity
流程图
1.首先检查插件是否已经初始化如果么有,就开始出初始化插件 创建Loader对象,调用loader中的LoadDex 来获取Dex中信息(四大组件信息)创建ComponentList, Resources,PluginDexClassLoader,PluginContext,等等,
2. loadEntryLocked 查找插件中Entry类,并调用Create方法,在create方法中,会初始化插件信息,为插件调用host方法做准备
3. callApp 检查并初始化Application 类,传递mPkgContext
4.获取activityInfo对象
流程图
1.根据插件processName获取进程标示
2.调用到PmBase.startPluginProcessLocked 检查插件是否已经初始化完成
3.分配进程编号PluginProcessMain.allocProcess 查找空闲的进程编号
4. PluginProviderStub.proxyStartPluginProcess启动进程,这里启动进程的方式很巧妙 (首先Mainifest中配置不同进程的Provider,然后根据进程编号调用不同的Provider当provider启动后它的进程也就启动啦)
5.当进程启动的时候,就会调用RePluginApplication 在这里会初始化进程信息,并通过 PluginProcessMain.connectToHostSvc();方法和host建立连接,并传递给host自己的client binder对象6.此时可以获取到client binder对象,
流程图
1. PluginContainers.alloc 根据activity的【是否透明,taskAffinity,launchMode,process】获取匹配一个已经在Mainifest配置好的Activity
2. 设置已经分配好的坑位信息,保存插件名称,真实activity信息,设置坑位已经使用状态
流程图
1.当调用context.startActivity 后,AMS最后会在ActivityThread中调用classLoader.loadClass 由于classLoader 已经替换成RePluginClassLoader
2. 在 RePluginClassLoader 的loadClass 调用的是PMF.loadClass 一步一步调用到 PluginProcessPer的 resolveActivityClass方法3. 在resolveActivityClass方法中 根据坑位查找到对应的真实activity 和插件信息,通过插件信息中的classloader加载真实的activity 达到偷梁换柱
1 在插件工程编译的时候gradle已经将activity的父类替换成对应的ReplugActivityxx 在这些activity中的attachBaseContext 方法中替换掉Context
2.通过newBase = RePluginInternal.createActivityContext(this, newBase);方法最终调用到Loader.java 里createBaseContext方法 new PluginContext 这样就替换掉Context
3.以后在activity中对context的操作都会调用PluginContext 方法
1 在插件工程编译的时候gradle已经将activity的父类替换成对应的ReplugActivityxx 在这些activity中的复写了onDestroy
2 在onDestory中调用RePluginInternal.handleActivityDestroy(this);方法,这个方法最终调用到PluginContainers类
3. PluginContainers.getInstance().recycle 回收对于的坑位
通过PluginServiceClient. startService 启动service
1.通话intent 在查找到ServiceInfo
2.通话PluginClientHelper.getProcessInt 获取到对应进程编号
3. 获取对应进程的PluginServiceServer对象 如果不存在启动对应的进程 (MP.startPluginProcess启动进程,在activity中已经讲述了如何启动进程这里就不多说啦)
4. 调用PluginServiceServer 的startService
5. 从ComponentList 中获取ServiceInfo
6. 获取插件信息,用对应的classLoader加载service,然后调用service 中的attachBaseContext方法传递context,设置mApplication,最后调用onCreate方法
7. 为了防止service被系统杀掉,这里会启动对应的坑位的service
stopServic主要实现是在PluginServiceServer里
1.service是否启动
2.当前serice是否bind,如果么有
3. recycleServiceLocked 回收servie ,调用onDestroy方法,并且停止坑位服务
bindService主要实现是在PluginServiceServer里和startService大部分相同 不同的是
1.检查是否bind过,如果没有回调用onBind
2.然后都有传递过来的对象的connected方法
unbindService主要实现是在PluginServiceServer里基本和stopSercie一样,这里就不多说
流程图
provider入口在PluginProviderClient类里 核心思想是
1.首先在Mainifet中配置一些坑位,这些坑位配置不同进程
2.通过PluginProviderClient的Uri turi = toCalledUri(c, uri);方法会把uri替换成
// from => content:// com.qihoo360.contacts.abc/people?id=9
// to => content://com.zcb.plugin.host.Plugin.NP.x /plugin_name/com.qihoo360.contacts.abc/people?id=9这样在调用c.getContentResolver().query/insert/xxx的时候就会调用到配置的坑位Provider 这些坑位的Provider都继承PluginPitProviderBase
3.在PluginPitProviderBase 类里在截取到真实的uri,更加真实的uri查询到ContentProvider 和插件信息
4.获取对应的classLoder加载ContentProvider 初始化Provider并 调用attachInfo方法传递Context
5.调用对应的方法 query/inster/update/xx
流程图
核心思想.receiver是在解析dex完成以后注册到host中一个总的receiver中,通过这个总的receiver代理转发 1.loader.loadDex 的时候解析出receiver,并通过regReceivers方法调用host中的 regReceiver方法
2.pmHostSvc regReceiver方法,将filter 通过mContext.registerReceiver(mReceiverProxy, filter);注册
3.当sendBroadcast的时候,mReceiverProxy接收到广播,根据action找到真实receiver以及插件信息
4.获取客户端client binder如果不存在就启动进程MP.startPluginProcess 详细见activity中进程启动方式解读
5.调用客户端的PluginReceiverHelper.onPluginReceiverReceived方法
6.获取classLoader 加载receiver 放入缓存,通过UI线程调用onReceive 方法
主要方式:
1.宿主启动的时候 applicaton的实现类配置的是RePluginApplication,在应用启动的时候调用attachBaseContext方法
1. attachBaseContext 方法会调用 RePlugin.App.attachBaseContext
2. PMF.init(app)会被调用 然后调用到 PmBase 中的init方法
3.init方法会调用initForServer 会初始化host信息,此时host 守护进程就启动啦
插件启动的时候 applicaton的实现类配置的是RePluginApplication,在应用启动的时候调用attachBaseContext方法
1. attachBaseContext 方法会调用 RePlugin.App.attachBaseContext
2. PMF.init(app)会被调用 然后调用到 PmBase 中的init方法
3.init方法在不是persistent的时候会调用initForClient
4. initForClient 调用PluginProcessMain.connectToHostSvc();
5.通过Provider 获取到hostBinder对象,然后和host 建立连接
6.再调用PMF.sPluginMgr.attach(); 把客户端clientBinder 注册到host里,
通过以上步骤,host里有clientBinder对象,插件里有hostBinder对象,两者就可以通信
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。