Android应用程序绑定服务(bindService)的过程源代码分析.docx_第1页
Android应用程序绑定服务(bindService)的过程源代码分析.docx_第2页
Android应用程序绑定服务(bindService)的过程源代码分析.docx_第3页
Android应用程序绑定服务(bindService)的过程源代码分析.docx_第4页
Android应用程序绑定服务(bindService)的过程源代码分析.docx_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android应用程序组件Service与Activity一样,既可以在新的进程中启动,也可以在应用程序进程内部启动;前面我们已经分析了在新的进程中启动Service的过程,本文将要介绍在应用程序内部绑定Service的过程,这是一种在应用程序进程内部启动Service的方法。 在前面一篇文章Android进程间通信(IPC)机制Binder简要介绍和学习计划中,我们就曾经提到,在Android系统中,每一个应用程序都是由一些Activity和Service组成的,一般Service运行在独立的进程中,而Activity有可能运行在同一个进程中,也有可能运行在不同的进程中;在接下来的文章中,Android系统在新进程中启动自定义服务过程(startService)的原理分析一文介绍了在新的进程中启动Service的过程,Android应用程序启动过程源代码分析一文介绍了在新的进程中启动Activity的过程,而Android应用程序内部启动Activity过程(startActivity)的源代码分析一文则介绍了在应用程序进程内部启动Activity的过程;本文接过最后一棒,继续介绍在应用程序进程内部启动Service的过程,这种过程又可以称在应用程序进程内部绑定服务(bindService)的过程,这样,读者应该就可以对Android应用程序启动Activity和Service有一个充分的认识了。 这里仍然是按照老规矩,通过具体的例子来分析Android应用程序绑定Service的过程,而所使用的例子便是前面我们在介绍Android系统广播机制的一篇文章Android系统中的广播(Broadcast)机制简要介绍和学习计划中所开发的应用程序Broadcast了。 我们先简单回顾一下这个应用程序实例绑定Service的过程。在这个应用程序的MainActivity的onCreate函数中,会调用bindService来绑定一个计数器服务CounterService,这里绑定的意思其实就是在MainActivity内部获得CounterService的接口,所以,这个过程的第一步就是要把CounterService启动起来。当CounterService的onCreate函数被调用起来了,就说明CounterService已经启动起来了,接下来系统还要调用CounterService的onBind函数,跟CounterService要一个Binder对象,这个Binder对象是在CounterService内部自定义的CounterBinder类的一个实例,它继承于Binder类,里面实现一个getService函数,用来返回外部的CounterService接口。系统得到这个Binder对象之后,就会调用MainActivity在bindService函数里面传过来的ServiceConnection实例的onServiceConnected函数,并把这个Binder对象以参数的形式传到onServiceConnected函数里面,于是,MainActivity就可以调用这个Binder对象的getService函数来获得CounterService的接口了。 这个过程比较复杂,但总体来说,思路还是比较清晰的,整个调用过程为MainActivity.bindService-CounterService.onCreate-CounterService.onBind-MainActivity.ServiceConnection.onServiceConnection-CounterService.CounterBinder.getService。下面,我们就先用一个序列图来总体描述这个服务绑定的过程,然后就具体分析每一个步骤。点击查看大图 Step 1. ContextWrapper.bindService 这个函数定义在frameworks/base/core/java/android/content/ContextWrapper.java文件中:view plain1. publicclassContextWrapperextendsContext2. ContextmBase;3. .4. 5. Override6. publicbooleanbindService(Intentservice,ServiceConnectionconn,7. intflags)8. returnmBase.bindService(service,conn,flags);9. 10. 11. .12. 这里的mBase是一个ContextImpl实例变量,于是就调用ContextImpl的bindService函数来进一步处理。 Step 2.ContextImpl.bindService 这个函数定义在frameworks/base/core/java/android/app/ContextImpl.java文件中:view plain1. classContextImplextendsContext2. .3. 4. Override5. publicbooleanbindService(Intentservice,ServiceConnectionconn,6. intflags)7. IServiceConnectionsd;8. if(mPackageInfo!=null)9. sd=mPackageInfo.getServiceDispatcher(conn,getOuterContext(),10. mMainThread.getHandler(),flags);11. else12. .13. 14. try15. intres=ActivityManagerNative.getDefault().bindService(16. mMainThread.getApplicationThread(),getActivityToken(),17. service,service.resolveTypeIfNeeded(getContentResolver(),18. sd,flags);19. .20. returnres!=0;21. catch(RemoteExceptione)22. returnfalse;23. 24. 25. 26. .27. 28. 这里的mMainThread是一个ActivityThread实例,通过它的getHandler函数可以获得一个Handler对象,有了这个Handler对象后,就可以把消息分发到ActivityThread所在的线程消息队列中去了,后面我们将会看到这个用法,现在我们暂时不关注,只要知道这里从ActivityThread处获得了一个Handler并且保存在下面要介绍的ServiceDispatcher中去就可以了。 我们先看一下ActivityThread.getHandler的实现,然后再回到这里的bindService函数来。 Step 3. ActivityThread.getHandler 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:view plain1. publicfinalclassActivityThread2. .3. 4. finalHmH=newH();5. 6. .7. 8. privatefinalclassHextendsHandler9. .10. 11. publicvoidhandleMessage(Messagemsg)12. .13. 14. 15. .16. 17. 18. .19. 20. finalHandlergetHandler()21. returnmH;22. 23. 24. .25. 这里返回的Handler是在ActivityThread类内部从Handler类继承下来的一个H类实例变量。 回到Step 2中的ContextImpl.bindService函数中,获得了这个Handler对象后,就调用mPackageInfo.getServiceDispatcher函数来获得一个IServiceConnection接口,这里的mPackageInfo的类型是LoadedApk,我们来看看它的getServiceDispatcher函数的实现,然后再回到ContextImpl.bindService函数来。 Step 4. LoadedApk.getServiceDispatcher 这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:view plain1. finalclassLoadedApk2. .3. 4. publicfinalIServiceConnectiongetServiceDispatcher(ServiceConnectionc,5. Contextcontext,Handlerhandler,intflags)6. synchronized(mServices)7. LoadedApk.ServiceDispatchersd=null;8. HashMapmap=mServices.get(context);9. if(map!=null)10. sd=map.get(c);11. 12. if(sd=null)13. sd=newServiceDispatcher(c,context,handler,flags);14. if(map=null)15. map=newHashMap();16. mServices.put(context,map);17. 18. map.put(c,sd);19. else20. sd.validate(context,handler);21. 22. returnsd.getIServiceConnection();23. 24. 25. 26. .27. 28. staticfinalclassServiceDispatcher29. privatefinalServiceDispatcher.InnerConnectionmIServiceConnection;30. privatefinalServiceConnectionmConnection;31. privatefinalHandlermActivityThread;32. .33. 34. privatestaticclassInnerConnectionextendsIServiceConnection.Stub35. finalWeakReferencemDispatcher;36. .37. 38. InnerConnection(LoadedApk.ServiceDispatchersd)39. mDispatcher=newWeakReference(sd);40. 41. 42. .43. 44. 45. .46. 47. ServiceDispatcher(ServiceConnectionconn,48. Contextcontext,HandleractivityThread,intflags)49. mIServiceConnection=newInnerConnection(this);50. mConnection=conn;51. mActivityThread=activityThread;52. .53. 54. 55. .56. 57. IServiceConnectiongetIServiceConnection()58. returnmIServiceConnection;59. 60. 61. .62. 63. 64. .65. 在getServiceDispatcher函数中,传进来的参数context是一个MainActivity实例,先以它为Key值在mServices中查看一下,是不是已经存在相应的ServiceDispatcher实例,如果有了,就不用创建了,直接取出来。在我们这个情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例的过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在了ServiceDispatcher实例的内部,并且创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。 函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。 Step 5. ActivityManagerService.bindService 这个函数定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:view plain1. classActivityManagerProxyimplementsIActivityManager2. 3. .4. 5. publicintbindService(IApplicationThreadcaller,IBindertoken,6. Intentservice,StringresolvedType,IServiceConnectionconnection,7. intflags)throwsRemoteException8. Parceldata=Parcel.obtain();9. Parcelreply=Parcel.obtain();10. data.writeInterfaceToken(IActivityManager.descriptor);11. data.writeStrongBinder(caller!=null?caller.asBinder():null);12. data.writeStrongBinder(token);13. service.writeToParcel(data,0);14. data.writeString(resolvedType);15. data.writeStrongBinder(connection.asBinder();16. data.writeInt(flags);17. mRemote.transact(BIND_SERVICE_TRANSACTION,data,reply,0);18. reply.readException();19. intres=reply.readInt();20. data.recycle();21. reply.recycle();22. returnres;23. 24. 25. .26. 这个函数通过Binder驱动程序就进入到ActivityManagerService的bindService函数去了。 Step 6. ActivityManagerService.bindService 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:view plain1. publicfinalclassActivityManagerServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3. .4. 5. publicintbindService(IApplicationThreadcaller,IBindertoken,6. Intentservice,StringresolvedType,7. IServiceConnectionconnection,intflags)8. .9. 10. synchronized(this)11. .12. finalProcessRecordcallerApp=getRecordForAppLocked(caller);13. .14. 15. ActivityRecordactivity=null;16. if(token!=null)17. intaindex=mMainStack.indexOfTokenLocked(token);18. .19. activity=(ActivityRecord)mMainStack.mHistory.get(aindex);20. 21. 22. .23. 24. ServiceLookupResultres=25. retrieveServiceLocked(service,resolvedType,26. Binder.getCallingPid(),Binder.getCallingUid();27. 28. .29. 30. ServiceRecords=res.record;31. 32. finallongorigId=Binder.clearCallingIdentity();33. 34. .35. 36. AppBindRecordb=s.retrieveAppBindingLocked(service,callerApp);37. ConnectionRecordc=newConnectionRecord(b,activity,38. connection,flags,clientLabel,clientIntent);39. 40. IBinderbinder=connection.asBinder();41. ArrayListclist=s.connections.get(binder);42. 43. if(clist=null)44. clist=newArrayList();45. s.connections.put(binder,clist);46. 47. clist.add(c);48. b.connections.add(c);49. if(activity!=null)50. if(activity.connections=null)51. activity.connections=newHashSet();52. 53. activity.connections.add(c);54. 55. b.client.connections.add(c);56. clist=mServiceConnections.get(binder);57. if(clist=null)58. clist=newArrayList();59. mServiceConnections.put(binder,clist);60. 61. 62. clist.add(c);63. 64. if(flags&Context.BIND_AUTO_CREATE)!=0)65. .66. if(!bringUpServiceLocked(s,service.getFlags(),false)67. return0;68. 69. 70. 71. .72. 73. 74. return1;75. 76. 77. .78. 函数首先根据传进来的参数token是MainActivity在ActivityManagerService里面的一个令牌,通过这个令牌就可以将这个代表MainActivity的ActivityRecord取回来了。 接着通过retrieveServiceLocked函数,得到一个ServiceRecord,这个ServiceReocrd描述的是一个Service对象,这里就是CounterService了,这是根据传进来的参数service的内容获得的。回忆一下在MainActivity.onCreate函数绑定服务的语句:view plain1. IntentbindIntent=newIntent(MainActivity.this,CounterService.class);2. bindService(bindIntent,serviceConnection,Context.BIND_AUTO_CREATE); 这里的参数service,就是上面的bindIntent了,它里面设置了CounterService类的信息(CounterService.class),因此,这里可以通过它来把CounterService的信息取出来,并且保存在ServiceRecord对象s中。 接下来,就是把传进来的参数connection封装成一个ConnectionRecord对象。注意,这里的参数connection是一个Binder对象,它的类型是LoadedApk.ServiceDispatcher.InnerConnection,是在Step 4中创建的,后续ActivityManagerService就是要通过它来告诉MainActivity,CounterService已经启动起来了,因此,这里要把这个ConnectionRecord变量c保存下来,它保在在好几个地方,都是为了后面要用时方便地取回来的,这里就不仔细去研究了,只要知道ActivityManagerService要使用它时就可以方便地把它取出来就可以了,具体后面我们再分析。 最后,传进来的参数flags的位Context.BIND_AUTO_CREATE为1(参见上面MainActivity.onCreate函数调用bindService函数时设置的参数),因此,这里会调用bringUpServiceLocked函数进一步处理。 Step 7.ActivityManagerService.bringUpServiceLocked 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:view plain1. publicfinalclassActivityManagerServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3. .4. 5. privatefinalbooleanbringUpServiceLocked(ServiceRecordr,6. intintentFlags,booleanwhileRestarting)7. .8. 9. finalStringappName=cessName;10. ProcessRecordapp=getProcessRecordLocked(appName,r.appInfo.uid);11. 12. if(app!=null&app.thread!=null)13. try14. realStartServiceLocked(r,app);15. returntrue;16. catch(RemoteExceptione)17. .18. 19. 20. 21. /Notrunning-getitstarted,andenqueuethisservicerecord22. /tobeexecutedwhentheappcomesup.23. if(startProcessLocked(appName,r.appInfo,true,intentFlags,24. service,,false)=null)25. .26. 27. 28. .29. 30. 31. .32. 回忆在Android系统中的广播(Broadcast)机制简要介绍和学习计划中一文中,我们没有在程序的AndroidManifest.xml配置文件中设置CounterService的process属性值,因此,它默认就为application标签的process属性值,而application标签的process属性值也没有设置,于是,它们就默认为应用程序的包名了,即这里的appName的值为shy.luo.broadcast。接下来根据appName和应用程序的uid值获得一个ProcessRecord记录,由于之前在启动MainActivity的时候,已经根据这个appName和uid值创建了一个ProcessReocrd对象(具体可以参考Android应用程序启动过程源代码分析一文),因此,这里取回来的app和app.thread均不为null,于是,就执行realStartServiceLocked函数来执行下一步操作了。 如果这里得到的ProcessRecord变量app为null,又是什么情况呢?在这种情况下,就会执行后面的startProcessLocked函数来创建一个新的进程,然后在这个新的进程中启动这个Service了,具体可以参考前面一篇文章Android系统在新进程中启动自定义服务过程(startService)的原理分析。 Step 8.ActivityManagerService.realStartServiceLocked 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:view plain1. publicfinalclassActivityManagerServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3. .4. 5. privatefinalvoidrealStartServiceLocked(ServiceRecordr,6. ProcessRecordapp)throwsRemoteException7. .8. r.app=app;9. .10. 11. app.services.add(r);12. .13. 14. try15. .16. app.thread.scheduleCreateService(r,r.serviceInfo);17. .18. finally19. .20. 21. 22. requestServiceBindingsLocked(r);23. 24. .25. 26. 27. .28. 这个函数执行了两个操作,一个是操作是调用app.thread.scheduleCreateService函数来在应用程序进程内部启动CounterService,这个操作会导致CounterService的onCreate函数被调用;另一个操作是调用requestServiceBindingsLocked函数来向CounterService要一个Binder对象,这个操作会导致CounterService的onBind函数被调用。 这里,我们先沿着app.thread.scheduleCreateService这个路径分析下去,然后再回过头来分析requestServiceBindingsLocked的调用过程。这里的app.thread是一个Binder对象的远程接口,类型为ApplicationThreadProxy。每一个Android应用程序进程里面都有一个ActivtyThread对象和一个ApplicationThread对象,其中是ApplicationThread对象是ActivityThread对象的一个成员变量,是ActivityThread与ActivityManagerService之间用来执行进程间通信的,具体可以参考Android应用程序启动过程源代码分析一文。 Step 9. ApplicationThreadProxy.scheduleCreateService 这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:view plain1. classApplicationThreadProxyimplementsIApplicationThread2. .3. 4. publicfinalvoidscheduleCreateService(IBindertoken,ServiceInfoinfo)5. throwsRemoteException6. Parceldata=Parcel.obtain();7. data.writeInterfaceToken(IApplicationThread.descriptor);8. data.writeStrongBinder(token);9. info.writeToParcel(data,0);10. mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION,data,null,11. IBinder.FLAG_ONEWAY);12. data.recycle();13. 14. 15. .16. 这里通过Binder驱动程序就进入到ApplicationThread的scheduleCreateService函数去了。 Step 10.ApplicationThread.scheduleCreateService 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:view plain1. publicfinalclassActivityThread2. .3. 4. privatefinalclassApplicationThreadextendsApplicationThreadNative5. .6. 7. publicfinalvoidscheduleCreateService(IBindertoken,8. Serv

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论