<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
一開始的目標是解決各種各樣的ANR問題的,我們知道,ANR總體上分有四種型別,這四種型別有三種是和四大元件相對應的,所以,如果想了解ANR發生的根因,對安卓四大元件的實現流程是必須要了解的,都不明白ANR如何觸發的,怎麼能完美的解決ANR的問題呢?
所以會寫一系列的文章,來分析四大組建的實現原理,同時也順帶講解四種型別的ANR是如何發生的。
本篇主要介紹service的完整實現流程,下一篇文章介紹Service中的ANR是如何產生的。
其實啟動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); } } } }
發我們發現,不論是建立service,還是通知執行service的生命流程,最終都執行了一個完成的通知,這有何意圖呢?是的,這個意圖就是和ANR相關的,我們下一章來講了。
前面一一講了實現的原理,我們最後再來做一個總結,儘量用一張圖+幾句話的方式來概括。
1.無論前臺啟動還是後臺啟動,最終都會走到ContextImpl這個最終實現類中的方法,完成和AMS的互動。
2.AMS中主要是ActiveServices完成的整個流程。其核心方法是realStartServiceLocked。
他首先啟動一個延時訊息,通過延時訊息進行超時的監測。
然後通知APP去生成Service。
通知APP側去完成Service的生命週期流程onStartCommand。
3.收到APP側執行完成的通知後,則取消註冊延時訊息。
到此這篇關於Android Service完整實現流程分析的文章就介紹到這了,更多相關Android Service內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45