今天小编给大家分享一下Android Service怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
一.APP侧启动Service
其实启动service和启动Activity是很相似的,都是APP通知系统侧,由系统侧完成的整个流程。
1.1 前台和后台启动
无论是Activity,还是service,还是Application,都继承自Context的抽象类,所以可以使用Context的各种功能,就比如这了要介绍的启动前台/后台service。
Context在安卓中,使用了一种典型的代理模式,我们调用的startService或者startForegroundService方法,最终都会委托给ContextImpl中的startService和startForegroundService来处理的。我们就来看下ContextImpl中的这两个方法:
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } @Override public ComponentName startForegroundService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, true, mUser); }
果然和我猜测的差不多,无论前台还是后台启动,其实最终都会走到一个方法中,只是配置参数的区别而已。最终都会走执行startServiceCommon方法。
1.2startServiceCommon
该方法中,通过binder通知系统的AMS完成对应的service的启动操作:
ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier());
接下来,我们就看下系统侧是如何处理Service启动流程的。
二.系统侧分发处理Service的启动逻辑
系统侧的处理我主要分为3块来讲:
系统接受APP侧的通知并转发
系统侧委托ActiveServices负责完成的处理流程
收到APP侧执行完成的回调,进行收尾操作
2.1 AMS接受启动service的通知
APP侧持有system_server进程的binder,上面讲到,它会通过binder方法startService完成对系统侧的通知。所以AMS的startService会收到这个通知。
我们看下代码,发现AMS会把整个service的逻辑全部交由ActiveServices来处理,代码如下:
try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); }
系统代码startServiceLocked方法中,代码虽然很长,但是却遵循着一个不变的宗旨:位语句,即前面处理各种异常的分支逻辑,把核心流程留到方法的最终来处理。
所以我们直接看startServiceLocked方法的最后一部分即可:
final ComponentName realResult = startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg, allowBackgroundActivityStarts, backgroundActivityStartsToken);
startServiceInnerLocked方法中,处理逻辑也是比较简单的,最终会交给bringUpServiceLocked方法来进行处理。而bringUpServiceLocked方法中则最终会交给realStartServiceLocked完成整个流程。好像系统代码都喜喜欢用realStart,Activity启动的流程中也有一个方法叫realStartActivity。
2.2realStartServiceLocked流程
realStartServiceLocked方法中,我们总结为三个流程:
bumpServiceExecutingLocked,启动超时检查。
thread.scheduleCreateService通知APP一侧去创建Service。
sendServiceArgsLocked通知APP执行Service的生命流程。
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app, IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg, boolean enqueueOomAdj) throws RemoteException { //1.启动超时检查 bumpServiceExecutingLocked(r, execInFg, "create", null ); ... //2.通知APP创建service thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.mState.getReportedProcState()); r.postNotification(); created = true; ... //3.通知执行service生命流程 sendServiceArgsLocked(r, execInFg, true); ... }
三.系统侧通知APP启动Service
一般情况下,APP侧会收到系统侧发过来两种类型的通知,
第一种:创建Service的任务通知
第二种:执行Service生命流程的通知,通知Service执行onStartCommand方法。
ApplicationThread接受通知并创建Service
系统侧持有APP侧的binder,会通过scheduleCreateService这个binder方法通知APP一侧进行相应的操作。而APP侧,完成这个工作接收的就是ApplicationThread中的scheduleCreateService方法。该方法收到通知后,通过handler切换到主线程处理:
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }
handle中,会切换到主线程执行ActivityThread的handleCreateService方法。
主要执行了如下的几段逻辑:
如果是首次创建App进程的话,则需要重新创建Application;
创建Service对象;
调用service的attach方法进行关联;
调用service的onCreate生命周期方法;
创建完成后,通过serviceDoneExecuting通知系统侧创建完成。
try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); Application app = packageInfo.makeApplication(false, mInstrumentation); final java.lang.ClassLoader cl; if (data.info.splitName != null) { cl = packageInfo.getSplitClassLoader(data.info.splitName); } else { cl = packageInfo.getClassLoader(); } service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); ContextImpl context = ContextImpl.getImpl(service .createServiceBaseContext(this, packageInfo)); if (data.info.splitName != null) { context = (ContextImpl) context.createContextForSplit(data.info.splitName); } if (data.info.attributionTags != null && data.info.attributionTags.length > 0) { final String attributionTag = data.info.attributionTags[0]; context = (ContextImpl) context.createAttributionContext(attributionTag); } // Service resources must be initialized with the same loaders as the application // context. context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); mServicesData.put(data.token, data); mServices.put(data.token, service); try { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
ApplicationThread接受通知并执行Service的生命流程
同样的,这里完成接受的是,仍然是ApplicationThread中的方法。这个流程中的接受方法是scheduleServiceArgs方法。
ApplicationThread中,收到通知后,通过handler把任务转交到主线程。
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) { List<ServiceStartArgs> list = args.getList(); for (int i = 0; i < list.size(); i++) { ServiceStartArgs ssa = list.get(i); ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = ssa.taskRemoved; s.startId = ssa.startId; s.flags = ssa.flags; s.args = ssa.args; sendMessage(H.SERVICE_ARGS, s); } }
接下来handler中切换到主线程会执行ActivityThread的handleServiceArgs方法。
handleServiceArgs方法主要会完成以下几件事:
找到对应的service,调用起onStartCommand方法;
通知系统侧回调完成。
private void handleServiceArgs(ServiceArgsData data) { CreateServiceData createData = mServicesData.get(data.token); Service s = mServices.get(data.token); if (s != null) { try { if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); data.args.prepareToEnterProcess(isProtectedComponent(createData.info), s.getAttributionSource()); } int res; if (!data.taskRemoved) { res = s.onStartCommand(data.args, data.flags, data.startId); } else { s.onTaskRemoved(data.args); res = Service.START_TASK_REMOVED_COMPLETE; } QueuedWork.waitToFinish(); try { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }
以上就是“Android Service怎么实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。