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

歡迎訪問 生活随笔!

生活随笔

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

Android

Android的服务(Service)(三)Service客户端的绑定与跨进程

發布時間:2025/3/15 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android的服务(Service)(三)Service客户端的绑定与跨进程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
繼續上篇的分析,接下來是第三個問題”Service與其客戶端的綁定如何實現,即跨進程調用問題“

(一)、Service的生命周期

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

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

服務于客戶端的綁定通過binder來實現的,就是客戶端去bind服務。來看看ContextImpl的bindServiceCommon方法

[java]?view plaincopy
  • private?boolean?bindServiceCommon(Intent?service,?ServiceConnection?conn,?int?flags,??
  • ????????UserHandle?user)?{??
  • ????IServiceConnection?sd;??
  • ????if?(mPackageInfo?!=?null)?{??
  • ????????sd?=?mPackageInfo.getServiceDispatcher(conn,?getOuterContext(),??
  • ????????????????mMainThread.getHandler(),?flags);??
  • ????}??
  • ????try?{??
  • ????????IBinder?token?=?getActivityToken();??
  • ????????if?(token?==?null?&&?(flags&BIND_AUTO_CREATE)?==?0?&&?mPackageInfo?!=?null??
  • ????????????????&&?mPackageInfo.getApplicationInfo().targetSdkVersion??
  • ????????????????<?android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)?{??
  • ????????????flags?|=?BIND_WAIVE_PRIORITY;??
  • ????????}??
  • ????????service.prepareToLeaveProcess();??
  • ????????int?res?=?ActivityManagerNative.getDefault().bindService(??
  • ????????????mMainThread.getApplicationThread(),?getActivityToken(),??
  • ????????????service,?service.resolveTypeIfNeeded(getContentResolver()),??
  • ????????????sd,?flags,?user.getIdentifier());??
  • ????????if?(res?<?0)?{??
  • ????????????throw?new?SecurityException(??
  • ????????????????????"Not?allowed?to?bind?to?service?"?+?service);??
  • ????????}??
  • ????????return?res?!=?0;??
  • ????}??
  • }??
  • 然后會去LoadedApk.java里面會創建用于跨進程連接的binder對象,就是一個ServiceDispatcher的InnerConnection。
    [java]?view plaincopy
  • public?final?IServiceConnection?getServiceDispatcher(ServiceConnection?c,??
  • ????????Context?context,?Handler?handler,?int?flags)?{??
  • ????synchronized?(mServices)?{??
  • ????????LoadedApk.ServiceDispatcher?sd?=?null;??
  • ????????//這里用一個map將所有的連接記錄都保存起來了??
  • ????????ArrayMap<ServiceConnection,?LoadedApk.ServiceDispatcher>?map?=?mServices.get(context);??
  • ????????if?(map?!=?null)?{??
  • ????????????sd?=?map.get(c);??
  • ????????}??
  • ????????if?(sd?==?null)?{??
  • ????????????sd?=?new?ServiceDispatcher(c,?context,?handler,?flags);??
  • ????????????if?(map?==?null)?{??
  • ????????????????map?=?new?ArrayMap<ServiceConnection,?LoadedApk.ServiceDispatcher>();??
  • ????????????????mServices.put(context,?map);??
  • ????????????}??
  • ????????????map.put(c,?sd);??
  • ????????}?else?{??
  • ????????????sd.validate(context,?handler);??
  • ????????}??
  • ????????return?sd.getIServiceConnection();??
  • ????}??
  • }??
  • [java]?view plaincopy
  • ????static?final?class?ServiceDispatcher?{??
  • ????????private?final?ServiceDispatcher.InnerConnection?mIServiceConnection;??
  • ????????private?final?ServiceConnection?mConnection;??
  • ??
  • ????????private?static?class?ConnectionInfo?{??
  • ????????????IBinder?binder;??
  • ????????????IBinder.DeathRecipient?deathMonitor;??
  • ????????}??
  • ??
  • ????????private?static?class?InnerConnection?extends?IServiceConnection.Stub?{??
  • ????????????final?WeakReference<LoadedApk.ServiceDispatcher>?mDispatcher;??
  • ??
  • ????????????InnerConnection(LoadedApk.ServiceDispatcher?sd)?{??
  • ????????????????mDispatcher?=?new?WeakReference<LoadedApk.ServiceDispatcher>(sd);??
  • ????????????}??
  • ????????????//這個方法就是在ActivityManagerService中執行綁定鏈接時的方法調用??
  • ????????????//這里的service毫無疑問就是遠程對象執行onBind時返回的那個咯??
  • ????????????//所以這里才是服務端和客戶端傳遞一個binder對象的通道,因為這個過程涉及到兩個跨進程操作,所以這么設計是必須也是合理的??
  • ????????????public?void?connected(ComponentName?name,?IBinder?service)?throws?RemoteException?{??
  • ????????????????LoadedApk.ServiceDispatcher?sd?=?mDispatcher.get();??
  • ????????????????if?(sd?!=?null)?{??
  • ????????????????????sd.connected(name,?service);??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ??
  • ????????private?final?ArrayMap<ComponentName,?ServiceDispatcher.ConnectionInfo>?mActiveConnections??
  • ????????????=?new?ArrayMap<ComponentName,?ServiceDispatcher.ConnectionInfo>();??
  • ??
  • ????????ServiceConnection?getServiceConnection()?{??
  • ????????????return?mConnection;??
  • ????????}??
  • ??
  • ????????IServiceConnection?getIServiceConnection()?{??
  • ????????????return?mIServiceConnection;??
  • ????????}??
  • ??
  • ????????public?void?connected(ComponentName?name,?IBinder?service)?{??
  • ????????????if?(mActivityThread?!=?null)?{??
  • ????????????????mActivityThread.post(new?RunConnection(name,?service,?0));??
  • ????????????}?else?{??
  • ????????????????doConnected(name,?service);??
  • ????????????}??
  • ????????}??
  • ??
  • ????????public?void?death(ComponentName?name,?IBinder?service)?{??
  • ????????????.......................??
  • ????????}??
  • ????????//實際執行connect??
  • ????????public?void?doConnected(ComponentName?name,?IBinder?service)?{??
  • ????????????ServiceDispatcher.ConnectionInfo?old;??
  • ????????????ServiceDispatcher.ConnectionInfo?info;??
  • ??
  • ????????????synchronized?(this)?{??
  • ????????????????if?(mForgotten)?{??
  • ????????????????????//?We?unbound?before?receiving?the?connection;?ignore??
  • ????????????????????//?any?connection?received.??
  • ????????????????????return;??
  • ????????????????}??
  • ????????????????old?=?mActiveConnections.get(name);??
  • ????????????????if?(old?!=?null?&&?old.binder?==?service)?{??
  • ????????????????????//?Huh,?already?have?this?one.??Oh?well!??
  • ????????????????????return;??
  • ????????????????}??
  • ??
  • ????????????????if?(service?!=?null)?{??
  • ????????????????????//?A?new?service?is?being?connected...?set?it?all?up.??
  • ????????????????????mDied?=?false;??
  • ????????????????????info?=?new?ConnectionInfo();??
  • ????????????????????info.binder?=?service;??
  • ????????????????????info.deathMonitor?=?new?DeathMonitor(name,?service);??
  • ????????????????????try?{??
  • ????????????????????????service.linkToDeath(info.deathMonitor,?0);??
  • ????????????????????????mActiveConnections.put(name,?info);??
  • ????????????????????}?catch?(RemoteException?e)?{??
  • ????????????????????????//?This?service?was?dead?before?we?got?it...??just??
  • ????????????????????????//?don't?do?anything?with?it.??
  • ????????????????????????mActiveConnections.remove(name);??
  • ????????????????????????return;??
  • ????????????????????}??
  • ??
  • ????????????????}?else?{??
  • ????????????????????//?The?named?service?is?being?disconnected...?clean?up.??
  • ????????????????????mActiveConnections.remove(name);??
  • ????????????????}??
  • ??
  • ????????????????if?(old?!=?null)?{??
  • ????????????????????old.binder.unlinkToDeath(old.deathMonitor,?0);??
  • ????????????????}??
  • ????????????}??
  • ??
  • ????????????//?If?there?was?an?old?service,?it?is?not?disconnected.??
  • ????????????if?(old?!=?null)?{??
  • ????????????????mConnection.onServiceDisconnected(name);??
  • ????????????}??
  • ????????????//?If?there?is?a?new?service,?it?is?now?connected.??
  • ????????????//?眼熟了吧,這就是我們在綁定服務后獲取遠程對象代理的回調咯??
  • ????????????if?(service?!=?null)?{??
  • ????????????????mConnection.onServiceConnected(name,?service);??
  • ????????????}??
  • ????????}??
  • ??????????
  • ????????public?void?doDeath(ComponentName?name,?IBinder?service)?{??
  • ????????????mConnection.onServiceDisconnected(name);??
  • ????????}??
  • ??
  • ????????private?final?class?RunConnection?implements?Runnable?{??
  • ????????????RunConnection(ComponentName?name,?IBinder?service,?int?command)?{??
  • ????????????????mName?=?name;??
  • ????????????????mService?=?service;??
  • ????????????????mCommand?=?command;??
  • ????????????}??
  • ??
  • ????????????public?void?run()?{??
  • ????????????????if?(mCommand?==?0)?{??
  • ????????????????????doConnected(mName,?mService);??
  • ????????????????}?else?if?(mCommand?==?1)?{??
  • ????????????????????doDeath(mName,?mService);??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????????private?final?class?DeathMonitor?implements?IBinder.DeathRecipient??
  • ????????{??
  • ????????????DeathMonitor(ComponentName?name,?IBinder?service)?{??
  • ????????????????mName?=?name;??
  • ????????????????mService?=?service;??
  • ????????????}??
  • ??
  • ????????????public?void?binderDied()?{??
  • ????????????????death(mName,?mService);??
  • ????????????}??
  • ??
  • ????????????final?ComponentName?mName;??
  • ????????????final?IBinder?mService;??
  • ????????}??
  • ?}??
  • 后面就是bind操作了,前面講生命周期時已經有提到過的,這里再把那個方法列一下:

    [java]?view plaincopy
  • int?bindServiceLocked(IApplicationThread?caller,?IBinder?token,????
  • ????????Intent?service,?String?resolvedType,????
  • ????????IServiceConnection?connection,?int?flags,?int?userId)?{????
  • ????....................????
  • ????ServiceLookupResult?res?=????
  • ????????retrieveServiceLocked(service,?resolvedType,????
  • ????????????????Binder.getCallingPid(),?Binder.getCallingUid(),?userId,?true,?callerFg);????
  • ????....................????????????
  • ????try?{????
  • ????????if?(unscheduleServiceRestartLocked(s,?callerApp.info.uid,?false))?{????
  • ????????????if?(DEBUG_SERVICE)?Slog.v(TAG,?"BIND?SERVICE?WHILE?RESTART?PENDING:?"????
  • ????????????????????+?s);????
  • ????????}????
  • ????????...................????
  • ????????//bindings中添加一起綁定請求,后續requestServiceBindingsLocked()流程中處理綁定接口????
  • ????????AppBindRecord?b?=?s.retrieveAppBindingLocked(service,?callerApp);????
  • ????????....................????
  • ????????if?((flags&Context.BIND_AUTO_CREATE)?!=?0)?{????
  • ????????????s.lastActivity?=?SystemClock.uptimeMillis();????
  • ????????????//如果攜帶的標志位中包含自動啟動,則進行創建服務的操作,代碼可以看前面,如果已經啟動了,其實是什么操作也不干的????
  • ????????????if?(bringUpServiceLocked(s,?service.getFlags(),?callerFg,?false)?!=?null)?{????
  • ????????????????return?0;????
  • ????????????}????
  • ????????}????
  • ??
  • ????????if?(s.app?!=?null)?{????
  • ????????????//?This?could?have?made?the?service?more?important.????
  • ????????????mAm.updateLruProcessLocked(s.app,?s.app.hasClientActivities,?b.client);????
  • ????????????mAm.updateOomAdjLocked(s.app);????
  • ????????}????
  • ????????????
  • ????????if?(s.app?!=?null?&&?b.intent.received)?{????
  • ????????????//?Service?is?already?running,?so?we?can?immediately????
  • ????????????//?publish?the?connection.????
  • ????????????//?如果服務已經啟動并且有綁定過了,直接返回binder對象,這里的conn就是前面提到的InnerConnection的代理,這里看到了connected操作其實是由<pre?name="code"?class="java">????????????????????//?InnerConnection它來完成的??
  • ????????????try?{????
  • ????????????????c.conn.connected(s.name,?b.intent.binder);????
  • ????????????}?catch?(Exception?e)?{????
  • ????????????????Slog.w(TAG,?"Failure?sending?service?"?+?s.shortName????
  • ????????????????????????+?"?to?connection?"?+?c.conn.asBinder()????
  • ????????????????????????+?"?(in?"?+?c.binding.client.processName?+?")",?e);????
  • ????????????}????
  • ??
  • ????????????//?If?this?is?the?first?app?connected?back?to?this?binding,????
  • ????????????//?and?the?service?had?previously?asked?to?be?told?when????
  • ????????????//?rebound,?then?do?so.????
  • ????????????//?從這里可以看出,一般情況下,onBind只會執行一次,除非請求doRebind????
  • ????????????//?這個標志位是舊的客戶端全部unbind之后自動設置上的????
  • ????????????if?(b.intent.apps.size()?==?1?&&?b.intent.doRebind)?{????
  • ????????????????requestServiceBindingLocked(s,?b.intent,?callerFg,?true);????
  • ????????????}????
  • ????????}?else?if?(!b.intent.requested)?{????
  • ????????????//服務還沒有綁定者,則執行后續操作將調用到onBind操作????
  • ????????????requestServiceBindingLocked(s,?b.intent,?callerFg,?false);????
  • ????????}????
  • ??
  • ????????getServiceMap(s.userId).ensureNotStartingBackground(s);????
  • ??
  • ????}?finally?{????
  • ????????Binder.restoreCallingIdentity(origId);????
  • ????}????
  • ??
  • ????return?1;????
  • }????
  • 大家有沒有在上面注意一個問題,InnerConnection中并沒有unConnected方法,那么解綁的時候又是如何通過這個連接通道執行回調的呢?大家可以看看前面講的unBind流程中,里面也是沒有任何地方會執行到這個操作的,它有的只是服務端的unBind和可能執行onDestory。那么什么時候會執行到ServiceConnection.onServiceDisconnected,事實上只有在遠程服務端那個binder死亡才會執行到的。這個就是通過為這個binder對象注冊一個IBinder.DeathRecipient,這是binder的死亡通知機制。這里就不講了。

    到這里Android中的服務已經簡要的分析了一下,不可能面面俱到也不會全都正確,還請大家多多指教。


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

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的Android的服务(Service)(三)Service客户端的绑定与跨进程的全部內容,希望文章能夠幫你解決所遇到的問題。

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