日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android的服务(Service)(二)Service的自动重启问题

發布時間:2025/3/15 Android 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android的服务(Service)(二)Service的自动重启问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

繼續上篇的分析,接下來是第二個問題”Service的自動重啟問題“

(一)、Service的生命周期

(二)、Service的自動重啟問題

??? 這里要說服務的自動重啟問題,這個問題其實很簡單,只有兩個關鍵的方法。代碼如下:
??? 這個方法在ActivityThread的一系列針對服務的handle方法中都有調用到ActivityManagerSerice的serviceDoneExecuting()方法,但是跟重啟有關的只有handleServiceArgs(),因為只有在這里才有一個叫res的參數會起作用。

[java]?view plaincopy
  • private?void?handleServiceArgs(ServiceArgsData?data)?{??
  • ????Service?s?=?mServices.get(data.token);??
  • ????if?(s?!=?null)?{??
  • ????????try?{??
  • ????????????if?(data.args?!=?null)?{??
  • ????????????????data.args.setExtrasClassLoader(s.getClassLoader());??
  • ????????????}??
  • ????????????int?res;??
  • ????????????if?(!data.taskRemoved)?{??
  • ????????????????//就是回調了用戶服務的onStartCommand生命周期,這個做應用的都知道了,??
  • ??
  • ????????????????//這里可以通過設置其返回值來控制自己的服務是否允許被重新啟動,順理成章的這個值就是res??
  • ????????????????res?=?s.onStartCommand(data.args,?data.flags,?data.startId);??
  • ????????????}?else?{??
  • ????????????????s.onTaskRemoved(data.args);??
  • ????????????????res?=?Service.START_TASK_REMOVED_COMPLETE;??
  • ????????????}??
  • ????????????...............??
  • ????????????try?{??
  • ????????????????//看看系統用這個值都干了一些什么導致有這個特性??
  • ????????????????ActivityManagerNative.getDefault().serviceDoneExecuting(??
  • ????????????????????????data.token,?1,?data.startId,?res);??
  • ????????????}?catch?(RemoteException?e)?{??
  • ????????????????//?nothing?to?do.??
  • ????????????}??
  • ????????????ensureJitEnabled();??
  • ????????}??
  • ????????..................??
  • ????}??
  • }??
  • ??? 下面就是這個特性的關鍵代碼,里面的注釋已經寫的很全了,關鍵其作用的就是stopIfKilled這個標志。
    [java]?view plaincopy
  • void?serviceDoneExecutingLocked(ServiceRecord?r,?int?type,?int?startId,?int?res)?{??
  • ????boolean?inDestroying?=?mDestroyingServices.contains(r);??
  • ????if?(r?!=?null)?{??
  • ????????if?(type?==?1)?{??
  • ????????????//?This?is?a?call?from?a?service?start...??take?care?of??
  • ????????????//?book-keeping.??
  • ????????????r.callStart?=?true;??
  • ????????????switch?(res)?{??
  • ????????????????case?Service.START_STICKY_COMPATIBILITY:??
  • ????????????????case?Service.START_STICKY:?{??
  • ????????????????????//?We?are?done?with?the?associated?start?arguments.??
  • ????????????????????r.findDeliveredStart(startId,?true);??
  • ????????????????????//?Don't?stop?if?killed.??
  • ????????????????????r.stopIfKilled?=?false;??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????????case?Service.START_NOT_STICKY:?{??
  • ????????????????????//?We?are?done?with?the?associated?start?arguments.??
  • ????????????????????r.findDeliveredStart(startId,?true);??
  • ????????????????????if?(r.getLastStartId()?==?startId)?{??
  • ????????????????????????//?There?is?no?more?work,?and?this?service??
  • ????????????????????????//?doesn't?want?to?hang?around?if?killed.??
  • ????????????????????????r.stopIfKilled?=?true;??
  • ????????????????????}??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????????case?Service.START_REDELIVER_INTENT:?{??
  • ????????????????????//?We'll?keep?this?item?until?they?explicitly??
  • ????????????????????//?call?stop?for?it,?but?keep?track?of?the?fact??
  • ????????????????????//?that?it?was?delivered.??
  • ????????????????????ServiceRecord.StartItem?si?=?r.findDeliveredStart(startId,?false);??
  • ????????????????????if?(si?!=?null)?{??
  • ????????????????????????si.deliveryCount?=?0;??
  • ????????????????????????si.doneExecutingCount++;??
  • ????????????????????????//?Don't?stop?if?killed.??
  • ????????????????????????r.stopIfKilled?=?true;??
  • ????????????????????}??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????????case?Service.START_TASK_REMOVED_COMPLETE:?{??
  • ????????????????????//?Special?processing?for?onTaskRemoved().??Don't??
  • ????????????????????//?impact?normal?onStartCommand()?processing.??
  • ????????????????????r.findDeliveredStart(startId,?true);??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????????default:??
  • ????????????????????throw?new?IllegalArgumentException(??
  • ????????????????????????????"Unknown?service?start?result:?"?+?res);??
  • ????????????}??
  • ????????????if?(res?==?Service.START_STICKY_COMPATIBILITY)?{??
  • ????????????????r.callStart?=?false;??
  • ????????????}??
  • ????????}??
  • ????????final?long?origId?=?Binder.clearCallingIdentity();??
  • ????????serviceDoneExecutingLocked(r,?inDestroying,?inDestroying);??
  • ????????Binder.restoreCallingIdentity(origId);??
  • ????}?else?{??
  • ????????Slog.w(TAG,?"Done?executing?unknown?service?from?pid?"??
  • ????????????????+?Binder.getCallingPid());??
  • ????}??
  • }??
  • ??? 那么這個標志位又是在哪些情況下使得服務可以重啟的呢?這種場景入口很多啊,比如系統清理進程等,總之就是APP Died的情況下,入口方法不列舉了,最后都會執行到這來:
    [java]?view plaincopy
  • final?void?killServicesLocked(ProcessRecord?app,?boolean?allowRestart)?{??
  • ????//?Report?disconnected?services.??
  • ????if?(false)?{??
  • ????????//?XXX?we?are?letting?the?client?link?to?the?service?for??
  • ????????//?death?notifications.??
  • ????????if?(app.services.size()?>?0)?{??
  • ????????????Iterator<ServiceRecord>?it?=?app.services.iterator();??
  • ????????????while?(it.hasNext())?{??
  • ????????????????ServiceRecord?r?=?it.next();??
  • ????????????????for?(int?conni=r.connections.size()-1;?conni>=0;?conni--)?{??
  • ????????????????????ArrayList<ConnectionRecord>?cl?=?r.connections.valueAt(conni);??
  • ????????????????????for?(int?i=0;?i<cl.size();?i++)?{??
  • ????????????????????????ConnectionRecord?c?=?cl.get(i);??
  • ????????????????????????if?(c.binding.client?!=?app)?{??
  • ????????????????????????????try?{??
  • ????????????????????????????????//c.conn.connected(r.className,?null);??
  • ????????????????????????????}?catch?(Exception?e)?{??
  • ????????????????????????????????//?todo:?this?should?be?asynchronous!??
  • ????????????????????????????????Slog.w(TAG,?"Exception?thrown?disconnected?servce?"??
  • ??????????????????????????????????????+?r.shortName??
  • ??????????????????????????????????????+?"?from?app?"?+?app.processName,?e);??
  • ????????????????????????????}??
  • ????????????????????????}??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????//?First?clear?app?state?from?services.??
  • ????for?(int?i=app.services.size()-1;?i>=0;?i--)?{??
  • ????????ServiceRecord?sr?=?app.services.valueAt(i);??
  • ????????synchronized?(sr.stats.getBatteryStats())?{??
  • ????????????sr.stats.stopLaunchedLocked();??
  • ????????}??
  • ????????if?(sr.app?!=?null)?{??
  • ????????????sr.app.services.remove(sr);??
  • ????????}??
  • ????????sr.app?=?null;??
  • ????????sr.isolatedProc?=?null;??
  • ????????sr.executeNesting?=?0;??
  • ????????sr.forceClearTracker();??
  • ????????if?(mDestroyingServices.remove(sr))?{??
  • ????????????if?(DEBUG_SERVICE)?Slog.v(TAG,?"killServices?remove?destroying?"?+?sr);??
  • ????????}??
  • ??
  • ????????final?int?numClients?=?sr.bindings.size();??
  • ????????for?(int?bindingi=numClients-1;?bindingi>=0;?bindingi--)?{??
  • ????????????IntentBindRecord?b?=?sr.bindings.valueAt(bindingi);??
  • ????????????if?(DEBUG_SERVICE)?Slog.v(TAG,?"Killing?binding?"?+?b??
  • ????????????????????+?":?shouldUnbind="?+?b.hasBound);??
  • ????????????b.binder?=?null;??
  • ????????????b.requested?=?b.received?=?b.hasBound?=?false;??
  • ????????}??
  • ????}??
  • ??
  • ????//?Clean?up?any?connections?this?application?has?to?other?services.??
  • ????for?(int?i=app.connections.size()-1;?i>=0;?i--)?{??
  • ????????ConnectionRecord?r?=?app.connections.valueAt(i);??
  • ????????removeConnectionLocked(r,?app,?null);??
  • ????}??
  • ????app.connections.clear();??
  • ??
  • ????ServiceMap?smap?=?getServiceMap(app.userId);??
  • ??
  • ????//?Now?do?remaining?service?cleanup.??
  • ????for?(int?i=app.services.size()-1;?i>=0;?i--)?{??
  • ????????ServiceRecord?sr?=?app.services.valueAt(i);??
  • ????????//?Sanity?check:?if?the?service?listed?for?the?app?is?not?one??
  • ????????//?we?actually?are?maintaining,?drop?it.??
  • ????????if?(smap.mServicesByName.get(sr.name)?!=?sr)?{??
  • ????????????ServiceRecord?cur?=?smap.mServicesByName.get(sr.name);??
  • ????????????Slog.wtf(TAG,?"Service?"?+?sr?+?"?in?process?"?+?app??
  • ????????????????????+?"?not?same?as?in?map:?"?+?cur);??
  • ????????????app.services.removeAt(i);??
  • ????????????continue;??
  • ????????}??
  • ??
  • ????????//?Any?services?running?in?the?application?may?need?to?be?placed??
  • ????????//?back?in?the?pending?list.??
  • ????????//?這里還是分很多種情況的??
  • ????????//?允許重啟時,如果當前服務所在進程crash超過兩次,并且不是persistent的進程就結束不會重啟了??
  • ????????if?(allowRestart?&&?sr.crashCount?>=?2?&&?(sr.serviceInfo.applicationInfo.flags??
  • ????????????????&ApplicationInfo.FLAG_PERSISTENT)?==?0)?{??
  • ????????????Slog.w(TAG,?"Service?crashed?"?+?sr.crashCount??
  • ????????????????????+?"?times,?stopping:?"?+?sr);??
  • ????????????EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,??
  • ????????????????????sr.userId,?sr.crashCount,?sr.shortName,?app.pid);??
  • ????????????bringDownServiceLocked(sr);??
  • ????????}?else?if?(!allowRestart)?{??
  • ????????????//?不允許重啟直接掛掉??
  • ????????????bringDownServiceLocked(sr);??
  • ????????}?else?{??
  • ????????????//??
  • ????????????boolean?canceled?=?scheduleServiceRestartLocked(sr,?true);??
  • ??
  • ????????????//?Should?the?service?remain?running???Note?that?in?the??
  • ????????????//?extreme?case?of?so?many?attempts?to?deliver?a?command??
  • ????????????//?that?it?failed?we?also?will?stop?it?here.??
  • ????????????if?(sr.startRequested?&&?(sr.stopIfKilled?||?canceled))?{??
  • ????????????????if?(sr.pendingStarts.size()?==?0)?{??
  • ????????????????????sr.startRequested?=?false;??
  • ????????????????????if?(sr.tracker?!=?null)?{??
  • ????????????????????????sr.tracker.setStarted(false,?mAm.mProcessStats.getMemFactorLocked(),??
  • ????????????????????????????????SystemClock.uptimeMillis());??
  • ????????????????????}??
  • ????????????????????if?(!sr.hasAutoCreateConnections())?{??
  • ????????????????????????//?Whoops,?no?reason?to?restart!??
  • ????????????????????????bringDownServiceLocked(sr);??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????if?(!allowRestart)?{??
  • ????????app.services.clear();??
  • ??
  • ????????//?Make?sure?there?are?no?more?restarting?services?for?this?process.??
  • ????????for?(int?i=mRestartingServices.size()-1;?i>=0;?i--)?{??
  • ????????????ServiceRecord?r?=?mRestartingServices.get(i);??
  • ????????????if?(r.processName.equals(app.processName)?&&??
  • ????????????????????r.serviceInfo.applicationInfo.uid?==?app.info.uid)?{??
  • ????????????????mRestartingServices.remove(i);??
  • ????????????????clearRestartingIfNeededLocked(r);??
  • ????????????}??
  • ????????}??
  • ????????for?(int?i=mPendingServices.size()-1;?i>=0;?i--)?{??
  • ????????????ServiceRecord?r?=?mPendingServices.get(i);??
  • ????????????if?(r.processName.equals(app.processName)?&&??
  • ????????????????????r.serviceInfo.applicationInfo.uid?==?app.info.uid)?{??
  • ????????????????mPendingServices.remove(i);??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????//?Make?sure?we?have?no?more?records?on?the?stopping?list.??
  • ????int?i?=?mDestroyingServices.size();??
  • ????while?(i?>?0)?{??
  • ????????i--;??
  • ????????ServiceRecord?sr?=?mDestroyingServices.get(i);??
  • ????????if?(sr.app?==?app)?{??
  • ????????????sr.forceClearTracker();??
  • ????????????mDestroyingServices.remove(i);??
  • ????????????if?(DEBUG_SERVICE)?Slog.v(TAG,?"killServices?remove?destroying?"?+?sr);??
  • ????????}??
  • ????}??
  • ??
  • ????app.executingServices.clear();??
  • }?????
  • [java]?view plaincopy
  • private?final?boolean?scheduleServiceRestartLocked(ServiceRecord?r,??
  • ????????boolean?allowCancel)?{??
  • ????boolean?canceled?=?false;??
  • ??
  • ????ServiceMap?smap?=?getServiceMap(r.userId);??
  • ????if?(smap.mServicesByName.get(r.name)?!=?r)?{??
  • ????????ServiceRecord?cur?=?smap.mServicesByName.get(r.name);??
  • ????????Slog.wtf(TAG,?"Attempting?to?schedule?restart?of?"?+?r??
  • ????????????????+?"?when?found?in?map:?"?+?cur);??
  • ????????return?false;??
  • ????}??
  • ??
  • ????final?long?now?=?SystemClock.uptimeMillis();??
  • ??
  • ????if?((r.serviceInfo.applicationInfo.flags??
  • ????????????&ApplicationInfo.FLAG_PERSISTENT)?==?0)?{??
  • ????????long?minDuration?=?SERVICE_RESTART_DURATION;??
  • ????????long?resetTime?=?SERVICE_RESET_RUN_DURATION;??
  • ??
  • ????????//?Any?delivered?but?not?yet?finished?starts?should?be?put?back??
  • ????????//?on?the?pending?list.??
  • ????????final?int?N?=?r.deliveredStarts.size();??
  • ????????if?(N?>?0)?{??
  • ????????????for?(int?i=N-1;?i>=0;?i--)?{??
  • ????????????????ServiceRecord.StartItem?si?=?r.deliveredStarts.get(i);??
  • ????????????????si.removeUriPermissionsLocked();??
  • ????????????????//注意了,這里的canceled如果為true還是需要結束服務的??
  • ????????????????//還要關注一下delivery的上限和doneExecuting的上限??
  • ????????????????if?(si.intent?==?null)?{??
  • ????????????????????//?We'll?generate?this?again?if?needed.??
  • ????????????????}?else?if?(!allowCancel?||?(si.deliveryCount?<?ServiceRecord.MAX_DELIVERY_COUNT??
  • ????????????????????????&&?si.doneExecutingCount?<?ServiceRecord.MAX_DONE_EXECUTING_COUNT))?{??
  • ????????????????????//重新在pendingStart中添加si,所以會在下次執行時重新帶入intent進去??
  • ????????????????????r.pendingStarts.add(0,?si);??
  • ????????????????????long?dur?=?SystemClock.uptimeMillis()?-?si.deliveredTime;??
  • ????????????????????dur?*=?2;??
  • ????????????????????if?(minDuration?<?dur)?minDuration?=?dur;??
  • ????????????????????if?(resetTime?<?dur)?resetTime?=?dur;??
  • ????????????????}?else?{??
  • ????????????????????Slog.w(TAG,?"Canceling?start?item?"?+?si.intent?+?"?in?service?"??
  • ????????????????????????????+?r.name);??
  • ????????????????????canceled?=?true;??
  • ????????????????}??
  • ????????????}??
  • ????????????r.deliveredStarts.clear();??
  • ????????}??
  • ??
  • ????????r.totalRestartCount++;??
  • ????????if?(r.restartDelay?==?0)?{??
  • ????????????r.restartCount++;??
  • ????????????r.restartDelay?=?minDuration;??
  • ????????}?else?{??
  • ????????????//?If?it?has?been?a?"reasonably?long?time"?since?the?service??
  • ????????????//?was?started,?then?reset?our?restart?duration?back?to??
  • ????????????//?the?beginning,?so?we?don't?infinitely?increase?the?duration??
  • ????????????//?on?a?service?that?just?occasionally?gets?killed?(which?is??
  • ????????????//?a?normal?case,?due?to?process?being?killed?to?reclaim?memory).??
  • ????????????if?(now?>?(r.restartTime+resetTime))?{??
  • ????????????????r.restartCount?=?1;??
  • ????????????????r.restartDelay?=?minDuration;??
  • ????????????}?else?{??
  • ????????????????r.restartDelay?*=?SERVICE_RESTART_DURATION_FACTOR;??
  • ????????????????if?(r.restartDelay?<?minDuration)?{??
  • ????????????????????r.restartDelay?=?minDuration;??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ??
  • ????????r.nextRestartTime?=?now?+?r.restartDelay;??
  • ??
  • ????????//?Make?sure?that?we?don't?end?up?restarting?a?bunch?of?services??
  • ????????//?all?at?the?same?time.??
  • ????????boolean?repeat;??
  • ????????do?{??
  • ????????????repeat?=?false;??
  • ????????????for?(int?i=mRestartingServices.size()-1;?i>=0;?i--)?{??
  • ????????????????ServiceRecord?r2?=?mRestartingServices.get(i);??
  • ????????????????if?(r2?!=?r?&&?r.nextRestartTime??
  • ????????????????????????>=?(r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)??
  • ????????????????????????&&?r.nextRestartTime??
  • ????????????????????????<?(r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN))?{??
  • ????????????????????r.nextRestartTime?=?r2.nextRestartTime?+?SERVICE_MIN_RESTART_TIME_BETWEEN;??
  • ????????????????????r.restartDelay?=?r.nextRestartTime?-?now;??
  • ????????????????????repeat?=?true;??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????}??
  • ????????}?while?(repeat);??
  • ??
  • ????}?else?{??
  • ????????//?Persistent?processes?are?immediately?restarted,?so?there?is?no??
  • ????????//?reason?to?hold?of?on?restarting?their?services.??
  • ????????r.totalRestartCount++;??
  • ????????r.restartCount?=?0;??
  • ????????r.restartDelay?=?0;??
  • ????????r.nextRestartTime?=?now;??
  • ????}??
  • ??
  • ????if?(!mRestartingServices.contains(r))?{??
  • ????????r.createdFromFg?=?false;??
  • ????????mRestartingServices.add(r);??
  • ????????r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(),?now);??
  • ????}??
  • ??
  • ????r.cancelNotification();??
  • ??
  • ????mAm.mHandler.removeCallbacks(r.restarter);??
  • ????//?最關鍵的操作在這里,忘ActivityManagerService的handler里面post一個重啟的Runnable??
  • ????//?這個東西前面啟動過程創建ServiceRecord時有的,很簡單就是一個ServiceRestarter,它里面保存了這個ServiceRecord本身??
  • ????//?重啟的時候根據這個record就可以直接啟動服務了??
  • ????mAm.mHandler.postAtTime(r.restarter,?r.nextRestartTime);??
  • ????r.nextRestartTime?=?SystemClock.uptimeMillis()?+?r.restartDelay;??
  • ????Slog.w(TAG,?"Scheduling?restart?of?crashed?service?"??
  • ????????????+?r.shortName?+?"?in?"?+?r.restartDelay?+?"ms");??
  • ????EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,??
  • ????????????r.userId,?r.shortName,?r.restartDelay);??
  • ??
  • ????return?canceled;??
  • }??
  • [java]?view plaincopy
  • private?class?ServiceRestarter?implements?Runnable?{??
  • ????private?ServiceRecord?mService;??
  • ??
  • ????void?setService(ServiceRecord?service)?{??
  • ????????mService?=?service;??
  • ????}??
  • ??
  • ????public?void?run()?{??
  • ????????synchronized(mAm)?{??
  • ????????????//后面的事情就順利成章了。??
  • ????????????performServiceRestartLocked(mService);??
  • ????????}??
  • ????}??
  • }??
  • ??? 整個這個過程中,有好幾個參數控制著是否需要重啟,也定了很多參數的上限等等,這里單獨列出來解釋一下。
    ??? ServiceRecord.crashCount、ServiceRecord.StartItem.deliveryCount、ServiceRecord.StartItem.doneExecutingCount
    ??? crashCount顧名思義啊,就是crash的次數,這個在handleAppCrashLocked()中自增的,很明顯每crash一次就會自增,沒什么好說的
    ??? deliveryCount也很好理解,他是屬于StartItem的,所以表示的是啟動信息,是執行onStartCommand方法的次數,也就是外部startService的次數
    ??? doneExecutingCount跟deliveryCount還很有關聯,類似的也是說的這個服務執行的次數,那么它們有什么區別呢?
    ??? 還有兩個標志位Service.START_FLAG_RETRY、Service.START_FLAG_REDELIVERY要一起看。這個在ActivesService.sendServiceArgsLocked()中可以看到。意思就是說這個服務是直接重啟還是重新發送發送請求。
    ??? 它們還是互斥的,這點在serviceDoneExecutingLocked()方法的START_REDELIVER_INTENT分支處理中可以得到結論,總的來說就是說onStartCommand返回START_STICKY是允許重啟,而START_REDELIVER_INTENT會重新將上次的intent請求發送出去,服務中會重新接收到這個。

    最后將在下篇論第三個問題

    (三)、Service與其客戶端的綁定如何實現,即跨進程調用問題。

    原文地址:http://blog.csdn.net/hehui1860/article/details/41743549

    總結

    以上是生活随笔為你收集整理的Android的服务(Service)(二)Service的自动重启问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。