ITPub博客

首页 > IT职业 > IT图书 > 滴滴开源Android插件化框架VirtualAPK原理分析

滴滴开源Android插件化框架VirtualAPK原理分析

IT图书 作者:mmmike 时间:2021-09-09 09:45:56 0 删除 编辑

概述

滴滴出行公司的首个对外开源项目 - VirtualAPK。地址:https://github.com/didi/VirtualAPK

滴滴自行研发了这款插件化框架,功能全面、兼容性好,还能够适用于有耦合的业务插件,这就是VirtualAPK存在的意义。业内认为,在加载耦合插件方面,VirtualAPK可以说是开源方案的首选。据说滴滴打车里面已经用上了,所以还是有必要一探究竟的~~

VirtualAPK 的工作流程如图所示:

图片描述

VirtualAPK 对于插件没有额外的约束,原生的 apk 即可作为一个插件。插件工程编译生成 apk 后,通过宿主 App 加载,每个插件 apk 被加载后,都会在宿主中创建一个单独的 LoadedPlugin 对象。如上图所示,通过这些 LoadedPlugin 对象,VirtualAPK 就可以管理插件并赋予插件新的意义,使其可以像手机中安装过的App一样运行。

Activity支持 中已经介绍过了,那么,简单的来看一下 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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-19

  • 博文量
    77
  • 访问量
    550