滴滴出行公司的首个对外开源项目 - VirtualAPK。地址:https://github.com/didi/VirtualAPK
滴滴自行研发了这款插件化框架,功能全面、兼容性好,还能够适用于有耦合的业务插件,这就是VirtualAPK存在的意义。业内认为,在加载耦合插件方面,VirtualAPK可以说是开源方案的首选。据说滴滴打车里面已经用上了,所以还是有必要一探究竟的~~
VirtualAPK 的工作流程如图所示:
VirtualAPK 对于插件没有额外的约束,原生的 apk 即可作为一个插件。插件工程编译生成 apk 后,通过宿主 App 加载,每个插件 apk 被加载后,都会在宿主中创建一个单独的 LoadedPlugin 对象。如上图所示,通过这些 LoadedPlugin 对象,VirtualAPK 就可以管理插件并赋予插件新的意义,使其可以像手机中安装过的App一样运行。
ActivityManagerProxy 是如何启动一个Service的。在执行 startService 等方法的时候,AMS 代理对象会相应的来执行以下这些方法:
private Object startService(Object proxy, Method method, Object[] args) throws Throwable {
IApplicationThread appThread = (IApplicationThread) args[0];
Intent target = (Intent) args[1];
ResolveInfo resolveInfo = this.mPluginManager.resolveService(target, 0); if (null == resolveInfo || null == resolveInfo.serviceInfo) { // is host service
return method.invoke(this.mActivityManager, args);
} return startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_START_SERVICE);
}private ComponentName startDelegateServiceForTarget(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) {
Intent wrapperIntent = wrapperTargetIntent(target, serviceInfo, extras, command); return mPluginManager.getHostContext().startService(wrapperIntent);
}private Intent wrapperTargetIntent(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) { // fill in service with ComponentName
target.setComponent(new ComponentName(serviceInfo.packageName, serviceInfo.name));
String pluginLocation = mPluginManager.getLoadedPlugin(target.getComponent()).getLocation(); // 这里进行判断,看是交给 LocalService,还是 RemoteService 处理
// LocalService 和 RemoteService 分别对应是否在新的进程中启动Activity
boolean local = PluginUtil.isLocalService(serviceInfo);
Class extends Service> delegate = local ? LocalService.class : RemoteService.class;
Intent intent = new Intent();
intent.setClass(mPluginManager.getHostContext(), delegate);
intent.putExtra(RemoteService.EXTRA_TARGET, target); // 保存一下这个的Command,对应执行不同操作
intent.putExtra(RemoteService.EXTRA_COMMAND, command);
intent.putExtra(RemoteService.EXTRA_PLUGIN_LOCATION, pluginLocation); if (extras != null) {
intent.putExtras(extras);
} return intent;
}
实际上包括我们调用 stopService(),AMS 代理对象最后变换后的意图,同样也是上面代码的最后两个个方法 startDelegateServiceForTarget 和 wrapperTargetIntent(),只不过 command 不一样。
所以本质上 AMS 作为代理,不管你执行启动或者关闭插件里面的 Service,他都是调用 LocalService 或者 RemoteService 的 startService 方法,在 LocalService 或者 RemoteService 的 onStartCommand() 下,根据 command 进行相应的操作。那么我们来看一下 LocalService 的 onStartCommand() 方法:
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { if (null == intent || !intent.hasExtra(EXTRA_TARGET) || !intent.hasExtra(EXTRA_COMMAND)) { return START_STICKY;
}
Intent target = intent.getParcelableExtra(EXTRA_TARGET); int command = intent.getIntExtra(EXTRA_COMMAND, 0); if (null == target || command 很显然,在这里面才对应去控制了插件Service的生命周期。具体代码就留给大家分析吧~~
http://www.apkbus.com/blog-873057-77578.html
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2872/viewspace-2811929/ ,如需转载,请注明出处,否则将追究法律责任。