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

http://blog.csdn.net/hehui1860/article/details/41743625


继续上篇的分析,接下来是第三个问题”Service与其客户端的绑定如何实现,即跨进程调用问题“

(一)、Service的生命周期

(二)、Service的自动重启问题

(三)、Service与其客户端的绑定如何实现,即跨进程调用问题。

服务于客户端的绑定通过binder来实现的,就是客户端去bind服务。来看看ContextImpl的bindServiceCommon方法

[java]  view plain copy
  1. private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,  
  2.         UserHandle user) {  
  3.     IServiceConnection sd;  
  4.     if (mPackageInfo != null) {  
  5.         sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),  
  6.                 mMainThread.getHandler(), flags);  
  7.     }  
  8.     try {  
  9.         IBinder token = getActivityToken();  
  10.         if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null  
  11.                 && mPackageInfo.getApplicationInfo().targetSdkVersion  
  12.                 < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {  
  13.             flags |= BIND_WAIVE_PRIORITY;  
  14.         }  
  15.         service.prepareToLeaveProcess();  
  16.         int res = ActivityManagerNative.getDefault().bindService(  
  17.             mMainThread.getApplicationThread(), getActivityToken(),  
  18.             service, service.resolveTypeIfNeeded(getContentResolver()),  
  19.             sd, flags, user.getIdentifier());  
  20.         if (res < 0) {  
  21.             throw new SecurityException(  
  22.                     "Not allowed to bind to service " + service);  
  23.         }  
  24.         return res != 0;  
  25.     }  
  26. }  
然后会去LoadedApk.java里面会创建用于跨进程连接的binder对象,就是一个ServiceDispatcher的InnerConnection。
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final IServiceConnection getServiceDispatcher(ServiceConnection c,  
  2.         Context context, Handler handler, int flags) {  
  3.     synchronized (mServices) {  
  4.         LoadedApk.ServiceDispatcher sd = null;  
  5.         //这里用一个map将所有的连接记录都保存起来了  
  6.         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);  
  7.         if (map != null) {  
  8.             sd = map.get(c);  
  9.         }  
  10.         if (sd == null) {  
  11.             sd = new ServiceDispatcher(c, context, handler, flags);  
  12.             if (map == null) {  
  13.                 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();  
  14.                 mServices.put(context, map);  
  15.             }  
  16.             map.put(c, sd);  
  17.         } else {  
  18.             sd.validate(context, handler);  
  19.         }  
  20.         return sd.getIServiceConnection();  
  21.     }  
  22. }  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     static final class ServiceDispatcher {  
  2.         private final ServiceDispatcher.InnerConnection mIServiceConnection;  
  3.         private final ServiceConnection mConnection;  
  4.   
  5.         private static class ConnectionInfo {  
  6.             IBinder binder;  
  7.             IBinder.DeathRecipient deathMonitor;  
  8.         }  
  9.   
  10.         private static class InnerConnection extends IServiceConnection.Stub {  
  11.             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;  
  12.   
  13.             InnerConnection(LoadedApk.ServiceDispatcher sd) {  
  14.                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);  
  15.             }  
  16.             //这个方法就是在ActivityManagerService中执行绑定链接时的方法调用  
  17.             //这里的service毫无疑问就是远程对象执行onBind时返回的那个咯  
  18.             //所以这里才是服务端和客户端传递一个binder对象的通道,因为这个过程涉及到两个跨进程操作,所以这么设计是必须也是合理的  
  19.             public void connected(ComponentName name, IBinder service) throws RemoteException {  
  20.                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();  
  21.                 if (sd != null) {  
  22.                     sd.connected(name, service);  
  23.                 }  
  24.             }  
  25.         }  
  26.   
  27.         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections  
  28.             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();  
  29.   
  30.         ServiceConnection getServiceConnection() {  
  31.             return mConnection;  
  32.         }  
  33.   
  34.         IServiceConnection getIServiceConnection() {  
  35.             return mIServiceConnection;  
  36.         }  
  37.   
  38.         public void connected(ComponentName name, IBinder service) {  
  39.             if (mActivityThread != null) {  
  40.                 mActivityThread.post(new RunConnection(name, service, 0));  
  41.             } else {  
  42.                 doConnected(name, service);  
  43.             }  
  44.         }  
  45.   
  46.         public void death(ComponentName name, IBinder service) {  
  47.             .......................  
  48.         }  
  49.         //实际执行connect  
  50.         public void doConnected(ComponentName name, IBinder service) {  
  51.             ServiceDispatcher.ConnectionInfo old;  
  52.             ServiceDispatcher.ConnectionInfo info;  
  53.   
  54.             synchronized (this) {  
  55.                 if (mForgotten) {  
  56.                     // We unbound before receiving the connection; ignore  
  57.                     // any connection received.  
  58.                     return;  
  59.                 }  
  60.                 old = mActiveConnections.get(name);  
  61.                 if (old != null && old.binder == service) {  
  62.                     // Huh, already have this one.  Oh well!  
  63.                     return;  
  64.                 }  
  65.   
  66.                 if (service != null) {  
  67.                     // A new service is being connected... set it all up.  
  68.                     mDied = false;  
  69.                     info = new ConnectionInfo();  
  70.                     info.binder = service;  
  71.                     info.deathMonitor = new DeathMonitor(name, service);  
  72.                     try {  
  73.                         service.linkToDeath(info.deathMonitor, 0);  
  74.                         mActiveConnections.put(name, info);  
  75.                     } catch (RemoteException e) {  
  76.                         // This service was dead before we got it...  just  
  77.                         // don't do anything with it.  
  78.                         mActiveConnections.remove(name);  
  79.                         return;  
  80.                     }  
  81.   
  82.                 } else {  
  83.                     // The named service is being disconnected... clean up.  
  84.                     mActiveConnections.remove(name);  
  85.                 }  
  86.   
  87.                 if (old != null) {  
  88.                     old.binder.unlinkToDeath(old.deathMonitor, 0);  
  89.                 }  
  90.             }  
  91.   
  92.             // If there was an old service, it is not disconnected.  
  93.             if (old != null) {  
  94.                 mConnection.onServiceDisconnected(name);  
  95.             }  
  96.             // If there is a new service, it is now connected.  
  97.             // 眼熟了吧,这就是我们在绑定服务后获取远程对象代理的回调咯  
  98.             if (service != null) {  
  99.                 mConnection.onServiceConnected(name, service);  
  100.             }  
  101.         }  
  102.           
  103.         public void doDeath(ComponentName name, IBinder service) {  
  104.             mConnection.onServiceDisconnected(name);  
  105.         }  
  106.   
  107.         private final class RunConnection implements Runnable {  
  108.             RunConnection(ComponentName name, IBinder service, int command) {  
  109.                 mName = name;  
  110.                 mService = service;  
  111.                 mCommand = command;  
  112.             }  
  113.   
  114.             public void run() {  
  115.                 if (mCommand == 0) {  
  116.                     doConnected(mName, mService);  
  117.                 } else if (mCommand == 1) {  
  118.                     doDeath(mName, mService);  
  119.                 }  
  120.             }  
  121.         }  
  122.         private final class DeathMonitor implements IBinder.DeathRecipient  
  123.         {  
  124.             DeathMonitor(ComponentName name, IBinder service) {  
  125.                 mName = name;  
  126.                 mService = service;  
  127.             }  
  128.   
  129.             public void binderDied() {  
  130.                 death(mName, mService);  
  131.             }  
  132.   
  133.             final ComponentName mName;  
  134.             final IBinder mService;  
  135.         }  
  136.  }  

后面就是bind操作了,前面讲生命周期时已经有提到过的,这里再把那个方法列一下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int bindServiceLocked(IApplicationThread caller, IBinder token,    
  2.         Intent service, String resolvedType,    
  3.         IServiceConnection connection, int flags, int userId) {    
  4.     ....................    
  5.     ServiceLookupResult res =    
  6.         retrieveServiceLocked(service, resolvedType,    
  7.                 Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);    
  8.     ....................            
  9.     try {    
  10.         if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {    
  11.             if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "    
  12.                     + s);    
  13.         }    
  14.         ...................    
  15.         //bindings中添加一起绑定请求,后续requestServiceBindingsLocked()流程中处理绑定接口    
  16.         AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);    
  17.         ....................    
  18.         if ((flags&Context.BIND_AUTO_CREATE) != 0) {    
  19.             s.lastActivity = SystemClock.uptimeMillis();    
  20.             //如果携带的标志位中包含自动启动,则进行创建服务的操作,代码可以看前面,如果已经启动了,其实是什么操作也不干的    
  21.             if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {    
  22.                 return 0;    
  23.             }    
  24.         }    
  25.   
  26.         if (s.app != null) {    
  27.             // This could have made the service more important.    
  28.             mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities, b.client);    
  29.             mAm.updateOomAdjLocked(s.app);    
  30.         }    
  31.             
  32.         if (s.app != null && b.intent.received) {    
  33.             // Service is already running, so we can immediately    
  34.             // publish the connection.    
  35.             // 如果服务已经启动并且有绑定过了,直接返回binder对象,这里的conn就是前面提到的InnerConnection的代理,这里看到了connected操作其实是由<pre name="code" class="java">                    // InnerConnection它来完成的  
  36.             try {    
  37.                 c.conn.connected(s.name, b.intent.binder);    
  38.             } catch (Exception e) {    
  39.                 Slog.w(TAG, "Failure sending service " + s.shortName    
  40.                         + " to connection " + c.conn.asBinder()    
  41.                         + " (in " + c.binding.client.processName + ")", e);    
  42.             }    
  43.   
  44.             // If this is the first app connected back to this binding,    
  45.             // and the service had previously asked to be told when    
  46.             // rebound, then do so.    
  47.             // 从这里可以看出,一般情况下,onBind只会执行一次,除非请求doRebind    
  48.             // 这个标志位是旧的客户端全部unbind之后自动设置上的    
  49.             if (b.intent.apps.size() == 1 && b.intent.doRebind) {    
  50.                 requestServiceBindingLocked(s, b.intent, callerFg, true);    
  51.             }    
  52.         } else if (!b.intent.requested) {    
  53.             //服务还没有绑定者,则执行后续操作将调用到onBind操作    
  54.             requestServiceBindingLocked(s, b.intent, callerFg, false);    
  55.         }    
  56.   
  57.         getServiceMap(s.userId).ensureNotStartingBackground(s);    
  58.   
  59.     } finally {    
  60.         Binder.restoreCallingIdentity(origId);    
  61.     }    
  62.   
  63.     return 1;    
  64. }    

 
大家有没有在上面注意一个问题,InnerConnection中并没有unConnected方法,那么解绑的时候又是如何通过这个连接通道执行回调的呢?大家可以看看前面讲的unBind流程中,里面也是没有任何地方会执行到这个操作的,它有的只是服务端的unBind和可能执行onDestory。那么什么时候会执行到ServiceConnection.onServiceDisconnected,事实上只有在远程服务端那个binder死亡才会执行到的。这个就是通过为这个binder对象注册一个IBinder.DeathRecipient,这是binder的死亡通知机制。这里就不讲了。 

到这里Android中的服务已经简要的分析了一下,不可能面面俱到也不会全都正确,还请大家多多指教。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值