从源码出发深入理解 Android Service
dsgfjuyjd
8年前
<p>本文是 Android 系统学习系列文章中的第三章节的内容,介绍了 Android Service 相关的基础知识,然后从源码的角度上分析 Service 的一些实现原理。</p> <h2><strong>0X00 Service 基础知识</strong></h2> <p>Service 作为 Android 提供的四大组件之一,主要负责一些没有前台显示的后台任务。即使应用本身不再可见,Service 的属性也能使得其在后台运行。除此之外,Service 也可以通过 Binder 机制,与界面甚至其他应用进行进程间通信,以实现相应的交互。这里需要简单说明的是,既然是后台任务,为什么不选用 Thread 了?选用 Service 和 Thread 的主要区别在于需不需要在应用不可见的时候依然保留。举例来说,新闻详情页面的数据请求,只用在当前页面生效,而音乐播放这些后台任务就可以通过 Service 的方式来实现。</p> <p>关于如何使用 Service,官方教程已经说明得足够详细了,如果对这些用法,还有不清晰的地方,请戳这里进行查看,-> <a href="/misc/goto?guid=4959675985954447381" rel="nofollow,noindex">官方教程</a> 。官方教程里面包括,startService 和 bindService 的区别,在不同场景下应该选用哪种 Service 实现方式。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/a9b4015e178a07bc5ef1334f89bc3e67.png"></p> <p style="text-align:center">Service 生命周期</p> <h2><strong>0X01 startService 调用流程</strong></h2> <p>从前面的教程里面,可以知道 Service 的启动一般有两种方式,分别是 bindService 和 startService。这里主要说明 startService, 具体的实现逻辑在 ContextImpl 中,我们看看源码是怎么实现的。</p> <pre> <code class="language-java">@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); }</code></pre> <p>接下来,看看方法内部具体是怎么实现的。</p> <pre> <code class="language-java">private ComponentName startServiceCommon(Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), getOpPackageName(), user.getIdentifier()); // ignore some codes... return cn; } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }</code></pre> <p>从上面的代码可以看到,这里是通过 ActivityManagerNative 来执行的。可能会觉得很熟悉。事实上这里采用的机制就是同样的。</p> <pre> <code class="language-java">private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } };</code></pre> <p>ActivityManagerNative 的 getDefault 方法是这么实现的。可以看到,gDefault 是类型为 IActivityManager 的 Binder 对象。而这个 Binder 对象可以看做是在 System Server 中的 ActivityManagerService 的句柄,通过这个 Binder 对象,可以跨进程调用 ActivityManagerService。</p> <p>如果上述内容不容易理解的话,我们可以类比地来看这个问题。我们遥控电视的时候,例如进行增加音量的操作,这个操作实际不是由遥控器完成的,而是电视中的电子元件完成的。遥控器会和电视进行协商,先声明有哪些操作可以执行,然后将这些协商后的操作在遥控器端和电视端 �� 都实现,区别在于电视机是真的实现,而遥控器只是发送操作指令而已。前面代码中提及的 gDefault 就是 ActivityManagerService 的遥控器。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/94192488e29e5ece23b46fde464ca06b.jpg"></p> <p style="text-align:center">电视遥控器</p> <p>接着往下看看电视端是具体怎么操作的,这里的电视端就是 ActivityManagerService.</p> <pre> <code class="language-java">@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // ignore some codes... synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } }</code></pre> <p>看起来具体的逻辑,都在类型为 ActiveServices 的 mServices 对象中。ActiveServices 是 AMS 专门用来管理 Service 的类,大部分和 Services 相关的逻辑都在这里面。</p> <pre> <code class="language-java">ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, String callingPackage, int userId) throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); // 调用进程的优先级是否足够 final boolean callerFg; if (caller != null) { // 能否找到相应的 Process final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when starting service " + service); } callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE; } else { callerFg = true; } // ignore some codes. final ServiceMap smap = getServiceMap(r.userId); boolean addToStarting = false; if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { // 避免同时有多个服务启动时,造成的性能问题,如果超过阈值后,就进行延迟 if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r); return r.name; } if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // Something else is starting, delay! Slog.i(TAG_SERVICE, "Delaying start of: " + r); smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { addToStarting = true; if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying, but counting as bg: " + r); } } return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); }</code></pre> <p>可以看到 startServiceLocked 主要进行了权限校验和为性能进行的调度,具体的逻辑,还在 startServiceInnerLocked 方法里面。</p> <pre> <code class="language-java">ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ProcessStats.ServiceState stracker = r.getTracker(); if (stracker != null) { // 跟踪 Service 内存试用状况 stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); } r.callStart = false; synchronized (r.stats.getBatteryStats()) { // 跟踪电池占用情况 r.stats.startRunningLocked(); } // 实际启动 Service String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false); if (error != null) { return new ComponentName("!!", error); } // 设置超时时间 if (r.startRequested && addToStarting) { boolean first = smap.mStartingBackground.size() == 0; smap.mStartingBackground.add(r); r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT; if (DEBUG_DELAYED_SERVICE) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here); } else if (DEBUG_DELAYED_STARTS) { Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r); } if (first) { smap.rescheduleDelayedStarts(); } } else if (callerFg) { smap.ensureNotStartingBackground(r); } return r.name; }</code></pre> <p>接下来看看 bringUpServiceLocked 是如何实现的,这里就是实际启动 Service 的地方。</p> <pre> <code class="language-java">private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) throws TransactionTooLargeException { if (r.app != null && r.app.thread != null) { // 目标Service已经启动 sendServiceArgsLocked(r, execInFg, false); return null; } if (!whileRestarting && r.restartDelay > 0) { // 正在重启,或者等待重启,直接返回 return null; } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent); // 从重启 Service 列表中移除 if (mRestartingServices.remove(r)) { // 重试计数 r.resetRestartCounter(); clearRestartingIfNeededLocked(r); } // 移除 delayed 的标示 if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } // Service 即将被启动,它所属的Package不能被停止 try { AppGlobals.getPackageManager().setPackageStoppedState( r.packageName, false, r.userId); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + r.packageName + ": " + e); } // isolated 变量主要是用于如下问题 // Service 可以通过 AndroidManifest 中的指令指定在单独的进程上运行 // 启动这个单独的进程,是一个耗时的过程,因而 isolated 标记起来后, // 可以避免在这个过程中又创建了一个进程 final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); // 如果应用进程已经创建,而且 Looper 线程已经准备完毕 // 那么就调用 realStartServiceLocked 实际启动 Service if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } } } else { app = r.isolatedProc; } // 应用进程还未创建,这里需要先启动应用进程 if (app == null) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", r.name, false, isolated, false)) == null) { String msg = "Unable to launch app " + r.appInfo.packageName + "/" + r.appInfo.uid + " for service " + r.intent.getIntent() + ": process is bad"; Slog.w(TAG, msg); bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc = app; } } if (!mPendingServices.contains(r)) { mPendingServices.add(r); } if (r.delayedStop) { // 准备停止 Service r.delayedStop = false; if (r.startRequested) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (in bring up): " + r); stopServiceLocked(r); } } return null; }</code></pre> <p>上面的代码较为复杂,这里进行下初步的总结。首先判断服务是否已经启动,或者正在重启中,则直接返回。其后,当前 Service 进程正在启动中,也直接返回。最后判断应用进程是否启动,如果没有启动进程,则先启动进程。</p> <pre> <code class="language-java">private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { // 如果主进程不存在,抛出异常 if (app.thread == null) { throw new RemoteException(); } r.app = app; // 记录重启和最后活动时间 r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); final boolean newService = app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, false, null); mAm.updateOomAdjLocked(); boolean created = false; try { if (LOG_SERVICE_START_STOP) { String nameTerm; int lastPeriod = r.shortName.lastIndexOf('.'); nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName; EventLogTags.writeAmCreateService( r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid); } synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } // 确保 Package Opt 工作完成 mAm.ensurePackageDexOpt(r.serviceInfo.packageName); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); // 通过 app.thread 的 binder 对象,通过创建目标 Service. app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { if (!created) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); // Cleanup. if (newService) { app.services.remove(r); r.app = null; } // Retry. if (!inDestroying) { scheduleServiceRestartLocked(r, false); } } } // 如果是通过 bindService 来执行的,这里就会通知客户端. requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null)); } // 通知调用 onStartCommand 接口 sendServiceArgsLocked(r, execInFg, true); if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } if (r.delayedStop) { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (from start): " + r); stopServiceLocked(r); } } }</code></pre> <p>上面代码的重点在于 app.thread , 这个 IApplicationThread 对象同样也是一个 Bindle 接口,与前文提交的 gDefault 不同之处在于两者的方向是相反的。前者是应用进程操作AMS,而后者则是AMS操作应用进程。IApplicationThread 对应的实现是 ApplicationThread,我们看看这个类是如何处理 scheduleCreateService 这个方法的。</p> <pre> <code class="language-java">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); }</code></pre> <p>原来还是通过 mH Handler 这种方式来执行的呀,这与前面文章提及的知识是完全一样的。在 Handler 中的 handleMessage 是如何处理 CREATE_SERVICE 这个消息的?</p> <pre> <code class="language-java">case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate"); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;</code></pre> <p>继续看 handleCreateService 方法的实现。</p> <pre> <code class="language-java">private void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to instantiate service " + data.info.name + ": " + 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.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); try { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }</code></pre> <p>方法实现相对简单,首先通过 ClassLoader 加载相关的 class 对象,然后将 Service 和 Application 绑定在一起,最后调用 Service 的 onCreate 方法。到此为止,Service 就完全启动了。</p> <p>如果使用 Service 的方式是 startService,那么在 Service 启动后,就可以执行 sendServiceArgsLocked 方法,从而在 Service 的 onStartCommand 里面可以执行相应的后台代码,需要特别说明的是,这个是执行在 UI 线程上的,因而建议不要执行耗时的任务,如果是耗时的任务,需要通过多线程的方式来避免主线程的阻塞。即使应用当前不在前台,阻塞 UI 线程,也是很不好的情况。</p> <p>我们看看 sendServiceArgsLocked 是如何实现的。</p> <pre> <code class="language-java">private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException { final int N = r.pendingStarts.size(); if (N == 0) { return; } while (r.pendingStarts.size() > 0) { Exception caughtException = null; ServiceRecord.StartItem si; try { r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent); } catch (TransactionTooLargeException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent=" + si.intent); caughtException = e; } catch (RemoteException e) { // Remote process gone... we'll let the normal cleanup take care of this. if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r); caughtException = e; } catch (Exception e) { Slog.w(TAG, "Unexpected exception", e); caughtException = e; } if (caughtException != null) { // Keep nesting count correct final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); if (caughtException instanceof TransactionTooLargeException) { throw (TransactionTooLargeException)caughtException; } break; } } }</code></pre> <p>这里通过循环的方式,将在队列中的消息,依次通过 app.thread 发布到应用进程中去,如果中途发生了 TransactionTooLargeException 异常,则会提前终止这个过程。 app.thread 的 scheduleServiceArgs 方法,也是通过 mH 这个 Handler 来执行的,发送的消息为 SERVICE_ARGS 。</p> <pre> <code class="language-java">case SERVICE_ARGS: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart"); handleServiceArgs((ServiceArgsData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;</code></pre> <pre> <code class="language-java">private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); if (s != null) { try { if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); data.args.prepareToEnterProcess(); } 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 { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { // nothing to do. } ensureJitEnabled(); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }</code></pre> <p>handleServiceArgs 方法中, s.onStartCommand 就是我们书写后台代码的地方,当这个方法执行完成后,又通过 gDefault 这个遥控器通知 AMS 来任务完成了。</p> <p>对于 startService 这种方式而言,是需要手动调用 stopSelf 方法来结束 Service 的,背后的原理与 startService 方法类似,这里就不再赘述。</p> <h2><strong>0X02 bindService 调用流程</strong></h2> <p>bindService 相较于 startService 要复杂一些,通过这种方式实现的 Service,容易多个组件绑定到它,通过 ServiceConnection 的方式来进行通信。当没有任何其他组件,连接到这个 Service 时,该 Service 会自动销毁。</p> <p>bindService 方法是这样声明的。</p> <pre> <code class="language-java">@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, Process.myUserHandle()); }</code></pre> <pre> <code class="language-java">private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) { // ignore some codes ... validateServiceIntent(service); try { // ignore some codes ... int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res != 0; } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }</code></pre> <p>可以看到同样是通过 gDefault 这个遥控器来通知 AMS 进行相应的操作的,原理与上面 startService 相同,接收到遥控器的指令后,ActiveServices 的 bindSericeLocked 方法开始执行。bindSericeLocked 在进行一些校验,确认进程创建成功等等步骤后,还是通过 app.thread 发送 BIND_SERVICE 消息,来执行对应的逻辑。</p> <pre> <code class="language-java">private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (DEBUG_SERVICE) Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }</code></pre> <p>在 onBind 方法,给调用者返回 Binder 对象,通过 publishService 方法通过到 AMS 内部去,我们看看接下来发生了什么。</p> <pre> <code class="language-java">public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }</code></pre> <p>ActiveServices 中的代码也相对简单, 遍历建立起的 ServiceConnection,并调用它们的 connected 方法,这也是我们需要编写后台代码的地方。</p> <pre> <code class="language-java">void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r + " " + intent + ": " + service); if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) { b.binder = service; b.requested = true; b.received = true; for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { continue; } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c); try { c.conn.connected(r.name, service); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.name + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }</code></pre> <h2><strong>0X03 总结</strong></h2> <p>Service 作为四大组件之一,提供了不需要前台页面情况下,在后台继续执行任务的能力。Service 一般有两种使用方式,分别是通过 startService 和 bindService,前者适合执行一次性的任务,而后者则具备一定交互的能力,可以用作处理相对复杂的后台逻辑。</p> <p> </p> <h3> </h3> <p> </p> <p>来自:http://www.jianshu.com/p/e85c63be4266</p> <p> </p>