您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android Service怎么實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
其實啟動service和啟動Activity是很相似的,都是APP通知系統側,由系統側完成的整個流程。
無論是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方法。
該方法中,通過binder通知系統的AMS完成對應的service的啟動操作:
ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier());
接下來,我們就看下系統側是如何處理Service啟動流程的。
系統側的處理我主要分為3塊來講:
1.系統接受APP側的通知并轉發
2.系統側委托ActiveServices負責完成的處理流程
3.收到APP側執行完成的回調,進行收尾操作
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。
realStartServiceLocked方法中,我們總結為三個流程:
1.bumpServiceExecutingLocked,啟動超時檢查。
2.thread.scheduleCreateService通知APP一側去創建Service。
3.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 /* oomAdjReason */); ... //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的任務通知
第二種:執行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方法。
主要執行了如下的幾段邏輯:
1.如果是首次創建App進程的話,則需要重新創建Application;
2.創建Service對象;
3.調用service的attach方法進行關聯;
4.調用service的onCreate生命周期方法;
5.創建完成后,通過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方法主要會完成以下幾件事:
1.找到對應的service,調用起onStartCommand方法;
2.通知系統側回調完成。
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怎么實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。