写点什么

Android 插件化-Service 篇,flutter 通知推送

用户头像
Android架构
关注
发布于: 刚刚
  • ": " + e.toString(), e);}}


try {if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);


ContextImpl context = ContextImpl.createAppContext(this, packageInfo);context.setOuterContext(service);


Application app = packageInfo.makeApplication(false, mInstrumentation);//初始化 Service,并调用其 onCreate 方法 service.attach(context, this, data.info.name, data.token, app,ActivityManager.getService());service.onCreate();//保存当前创建的 Service 对应,用于后续执行 onStart、onBind、unBind 以及 onDestroy 等方法 mServices.put(data.token, service);try {ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to create service " + data.info.name


  • ": " + e.toString(), e);}}}

2、其他生命周期方法

Service 的其它相关生命期方法与ActivityThread.java源码中方法实现分别对应关系如下:


onStartCommand:handleServiceArgs


onBind:handleBindService


onUnbind:handleUnbindService


onDestroy:handleStopService


看完源码实现之后你会发现,上述的几个生命周期方法所操作的 Service 实例对象都是在


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


方法 handleCreateService 中所创建的对象。因此对于 Service 的插件化实现我们只需要拦截方法 handleCreateService 就足以。

三、Service 插件化的实现

1、实现步骤

有了上述源码的理解分析以及上一篇所实现Activity插件化的加持,对于 Service 插件化的实现那简直不要太简单。大致可以分为如下几个步骤:


第一步复用 Activity 插件化中所实现的 AMNHook 以及 ActivityThread 中 Handler 的 hook


第二步就是在 hook 的 AMN 中对操作 Service 的相关方法 startService、startService 以及 bindService 三个方法进行拦截,并将要启动的 Service 替换成在宿主中所预埋的 Service;


第三步就是在所 hook 的 Handler 中对方法 handleCreateService 进行拦截了。

2、代码实现

因为 AMN 以及对应 Handler 的 hook 在Activity篇中有做注解,所以这里就不做过多的赘述了, 我们直接跳到第二步的代码实现。


/***


  • @param realIntent 上层应用所构造 Intent 对象

  • @param name 上层应用所调用的方法,没啥实际用处,只是为了打印*/private void hookServiceOperate(Intent realIntent, String name) {if (null != realIntent) {ComponentName pluginComponentName = realIntent.getComponent();if (null != pluginComponentName) {String pluginServiceName = pluginComponentName.getClassName();//获取要启动的插件 Service 所对应的宿主 Service 名字哦 String hostServiceName = HostToPluginMapping.getHostService(pluginServiceName);if (!TextUtils.isEmpty(hostServiceName)) {Log.i(TAG, "current is hooking " + name);//将实际要启动的 Service 替换成宿主中 Service 以欺骗 AMSComponentName componentName = new ComponentName(pluginComponentName.getPackageName(), hostServiceName);realIntent.setComponent(componentName);}}}}


看着是不是 so easy,简单来说就是吧上层应用需要启动的插件 Service 替换成宿主中预埋的 Service 以欺骗 AMS;


最后就是在所 hook 的 Handler 中拦截方法 handleCreateService 了,对应的实现如下:


public void handleCreateService(Object object) {try {//首先获取从 AMS 传递过来的 CreateServiceData 对象中的 ServiceInfo 属性 ServiceInfo serviceInfo = (ServiceInfo) RefInvoke.getFieldValue(RefInvoke.getField(object.getClass(), "info"), object);String hostServiceName = serviceInfo.name;String pluginServiceName = HostToPluginMapping.getPluginService(hostServiceName);if (TextUtils.isEmpty(pluginServiceName)) {Log.i(TAG, "not found host service,so no need replace");return;}String path = DePluginSP.getInstance(DePluginApplication.getContext()).getString(Constants.COPY_FILE_PATH, "");//接着就是复用 Activity 插件化实现中的生成 LoadedApk 对象,并将其中的 ClassLoader 替换成加载对应插件的 ClassLoader 了 replaceClassloader(path);


//接着就是将 ServiceInfo 中的 ServiceName 替换成对应插件的 ServiceName 了,用于后续加载插件对应的 ServiceserviceInfo.name = pluginServiceName;serviceInfo.applicationInfo.packageName = mPathToPluginNameMap.get(path);Log.i(TAG, "replaced to plugin service success");} catch (Exception e) {Log.i(TAG, "handle create service failed");}......//最后就是继续调用到 ActivityThread 中的 handleCreateService 方法生成对应的 Service 对象,并做初始化等动作}

3、mergeDex

当然对于插件 Service 类的加载其实不用生成 ClassLoader 这么麻烦,我们可以将插件对应的 dex 文件通过 mergeDex 的方式添加到 BaseDexClassLoader 的 pathList 中,这样就能够直接通过当前应用默认的 ClassLoader 进行加载了,这也是 Android 中热修复实现的方式之一。对应的实现如下:

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android插件化-Service篇,flutter通知推送