搜索
 找回密码
 立即注册

简单一步 , 微信登陆

Android应用程序绑定服务(bindService)的过程源代码分析(2)

作者:liuwei | 时间:2016-10-11 17:44:29 | 阅读:3704| 只看该作者
这里的参数r就是我们在前面的Step 6中创建的ServiceRecord了,它代表刚才已经启动了的CounterService。函数requestServiceBindingsLocked调用了requestServiceBindingLocked函数来处理绑定服务的操作,而函数requestServiceBindingLocked又调用了app.thread.scheduleBindService函数执行操作,前面我们已经介绍过app.thread,它是一个Binder对象的远程接口,类型是ApplicationThreadProxy。
        Step 16. ApplicationThreadProxy.scheduleBindService
        这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:


  • public final class ActivityThread {
  •     ......
  •     public final void scheduleBindService(IBinder token, Intent intent,
  •             boolean rebind) {
  •         BindServiceData s = new BindServiceData();
  •         s.token = token;
  •         s.intent = intent;
  •         s.rebind = rebind;
  •         queueOrSendMessage(H.BIND_SERVICE, s);
  •     }
  •     ......
  • }
        这里像上面的Step 11一样,调用ActivityThread.queueOrSendMessage函数来发送消息。
        Step 18. ActivityThread.queueOrSendMessage
        参考上面的Step 11,不过这里的消息类型是H.BIND_SERVICE。
        Step 19. H.sendMessage
        参考上面的Step 12,不过这里最终在H.handleMessage函数中,要处理的消息类型是H.BIND_SERVICE:


  • public final class ActivityThread {
  •     ......
  •     private final void handleBindService(BindServiceData data) {
  •         Service s = mServices.get(data.token);
  •         if (s != null) {
  •             try {
  •                 data.intent.setExtrasClassLoader(s.getClassLoader());
  •                 try {
  •                     if (!data.rebind) {
  •                         IBinder binder = s.onBind(data.intent);
  •                         ActivityManagerNative.getDefault().publishService(
  •                             data.token, data.intent, binder);
  •                     } else {
  •                         ......
  •                     }
  •                     ......
  •                 } catch (RemoteException ex) {
  •                 }
  •             } catch (Exception e) {
  •                 ......
  •             }
  •         }
  •     }
  •     ......
  • }
        在前面的Step 13执行ActivityThread.handleCreateService函数中,已经将这个CounterService实例保存在mServices中,因此,这里首先通过data.token值将它取回来,保存在本地变量s中,接着执行了两个操作,一个操作是调用s.onBind,即CounterService.onBind获得一个Binder对象,另一个操作就是把这个Binder对象传递给ActivityManagerService。
        我们先看CounterService.onBind操作,然后再回到ActivityThread.handleBindService函数中来。
        Step 21. CounterService.onBind
        这个函数定义在应用程序Broadcast的工程目录下的src/shy/luo/broadcast/CounterService.java文件中:


  • class ActivityManagerProxy implements IActivityManager
  • {
  •     ......
  •     public void publishService(IBinder token,
  •     Intent intent, IBinder service) throws RemoteException {
  •         Parcel data = Parcel.obtain();
  •         Parcel reply = Parcel.obtain();
  •         data.writeInterfaceToken(IActivityManager.descriptor);
  •         data.writeStrongBinder(token);
  •         intent.writeToParcel(data, 0);
  •         data.writeStrongBinder(service);
  •         mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
  •         reply.readException();
  •         data.recycle();
  •         reply.recycle();
  •     }
  •     ......
  • }
         这里通过Binder驱动程序就进入到ActivityManagerService的publishService函数中去了。
         Step 23. ActivityManagerService.publishService
         这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:


  •    ServiceRecord s = res.record;
  •    ......
  •    ConnectionRecord c = new ConnectionRecord(b, activity,
  •     connection, flags, clientLabel, clientIntent);
  •    IBinder binder = connection.asBinder();
  •    ArrayList<ConnectionRecord> clist = s.connecti**.get(binder);
  •    if (clist == null) {
  • clist = new ArrayList<ConnectionRecord>();
  • s.connecti**.put(binder, clist);
  •    }
        因此,这里可以从r.connecti**中将这个ConnectionRecord取出来:


  • final class LoadedApk {
  •     ......
  •     static final class ServiceDispatcher {
  •         ......
  •         private static class InnerConnection extends IServiceConnection.Stub {
  •             ......
  •             public void connected(ComponentName name, IBinder service) throws RemoteException {
  •                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
  •                 if (sd != null) {
  •                     sd.connected(name, service);
  •                 }
  •             }
  •             ......
  •         }
  •         ......
  •     }
  •     ......
  • }
         这里它将操作转发给ServiceDispatcher.connected函数。
         Step 25. ServiceDispatcher.connected
         这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:


  • final class LoadedApk {
  •     ......
  •     static final class ServiceDispatcher {
  •         ......
  •         private final class RunConnection implements Runnable {
  •             ......
  •             public void run() {
  •                 if (mCommand == 0) {
  •                     doConnected(mName, mService);
  •                 } else if (mCommand == 1) {
  •                     ......
  •                 }
  •             }
  •             ......
  •         }
  •         ......
  •     }
  •     ......
  • }
        这里的mCommand值为0,于是就执行ServiceDispatcher.doConnected函数来进一步操作了。
        Step 28. ServiceDispatcher.doConnected
        这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:


  • public class MainActivity extends Activity implements OnClickListener {
  •     ......
  •     private ServiceConnection serviceConnection = new ServiceConnection() {
  •         public void **erviceConnected(ComponentName className, IBinder service) {
  •             counterService = ((CounterService.CounterBinder)service).getService();
  •             Log.i(LOG_TAG, "Counter Service Connected");
  •         }
  •         ......
  •     };
  •     ......
  • }
        这里传进来的参数service是一个Binder对象,就是前面在Step 21中从CounterService那里得到的ConterBinder对象,因此,这里可以把它强制转换为CounterBinder引用,然后调用它的getService函数。
        至此,应用程序绑定服务过程中的第三步MainActivity.ServiceConnection.**erviceConnection就完成了。
        Step 30. CounterBinder.getService
        这个函数定义在应用程序Broadcast的工程目录下的src/shy/luo/broadcast/CounterService.java文件中:


  • public class CounterService extends Service implements ICounterService {
  •     ......
  •     public class CounterBinder extends Binder {
  •         public CounterService getService() {
  •             return CounterService.this;
  •         }
  •     }
  •     ......
  • }
        这里就把CounterService接口返回给MainActivity了。        至此,应用程序绑定服务过程中的第四步CounterService.CounterBinder.getService就完成了。        这样,Android应用程序绑定服务(bindService)的过程的源代码分析就完成了,总结一下这个过程:
        1. Step 1 -  Step 14,MainActivity调用bindService函数通知ActivityManagerService,它要启动CounterService这个服务,ActivityManagerService于是在MainActivity所在的进程内部把CounterService启动起来,并且调用它的onCreate函数;        2. Step 15 - Step 21,ActivityManagerService把CounterService启动起来后,继续调用CounterService的onBind函数,要求CounterService返回一个Binder对象给它;        3. Step 22 - Step 29,ActivityManagerService从CounterService处得到这个Binder对象后,就把它传给MainActivity,即把这个Binder对象作为参数传递给MainActivity内部定义的ServiceConnection对象的**erviceConnected函数;        4. Step 30,MainActivity内部定义的ServiceConnection对象的**erviceConnected函数在得到这个Binder对象后,就通过它的getService成同函数获得CounterService接口。
收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版