【Android源码 栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了Android源码 -Android应用程序绑定服务(bindService)的过程源代码分析 - 电子设计的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
Android应用程序绑定服务bindService的过程源代码分析
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-gtCounterService.onCreate-gtCounterService.onBind-gtMainActivity.ServiceConnection.onServiceConnection-gtCounterService.CounterBinder.getService。
下面我们就先用一个序列图来总体描述这个服务绑定的过程然后就具体分析每一个步骤。
点击查看大图 Step 1. ContextWrapper.bindService 这个函数定义在frameworks/base/core/java/
android/content/ContextWrapper.java文件中 java view plaincopy 1. public class ContextWrapper extends Context 2. Context mBase 3. ...... 4. 5. Override 6. public boolean bindServiceIntent service ServiceConnection conn 7. int flags 8. return mBase.bindServiceservice conn flags 9. 10. 11. ...... 12. 这里的mBase是一个ContextImpl实例变量于是就调用ContextImpl的bindService函数来进一步处理。
Step 2. ContextImpl.bindService 这个函数定义在frameworks/base/core/java/
android/app/ContextImpl.java文件中 java view plaincopy 1. class ContextImpl extends Context 2. ...... 3. 4. Override 5. public boolean bindServiceIntent service ServiceConnection conn 6. int flags 7. IServiceConnection sd 8. if mPackageInfo null 9. sd mPackageInfo.getServiceDispatcherconn getOuterContext 10. mMainThread.getHandler flags 11. else 12. ...... 13. 14. try 15. int res ActivityManagerNative.getDefault.bindService 16. mMainThread.getApplicationThread getActivityToken 17. service service.resolveTypeIfNeededgetContentResolver 18. sd flags 19. ...... 20. return res 0 21. catch RemoteException e 22. return false 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文件中 java view plaincopy 1. public final class ActivityThread 2. ...... 3. 4. final H mH new H 5. 6. ...... 7. 8. private final class H extends Handler 9. ...... 10. 11. public void handleMessageMessage msg 12. ...... 13. 14. 15. ...... 16. 17. 18. ...... 19. 20. final Handler getHandler 21. return mH 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文件中 java view plaincopy 1. final class LoadedApk 2. ...... 3. 4. public final IServiceConnection getServiceDispatcherServiceConnection c 5. Context context Handler handler int flags 6. synchronized mServices 7. LoadedApk.ServiceDispatcher sd null 8. HashMapltServiceConnection LoadedApk.ServiceDispatchergt map mServices.getcontext 9. if map null 10. sd map.getc 11. 12. if sd null 13. sd new ServiceDispatcherc context handler flags 14. if map null 15. map new HashMapltServiceConnection LoadedApk.ServiceDispatchergt 16. mServices.putcontext map 17. 18. map.putc sd 19. else 20. sd.validatecontext handler 21. 22. return sd.getIServiceConnection 23. 24. 25. 26. ...... 27. 28. static final class ServiceDispatcher 29. private final ServiceDispatcher.InnerConnection mIServiceConnection 30. private final ServiceConnection mConnection 31. private final Handler mActivityThread 32. ...... 33. 34. private static class InnerConnection extends IServiceConnection.Stub 35. final WeakReferenceltLoadedApk.ServiceDispatchergt mDispatcher 36. ...... 37. 38. InnerConnectionLoadedApk.ServiceDispatcher sd 39. mDispatcher new WeakReferenceltLoadedApk.ServiceDispatchergtsd 40. 41. 42. ...... 43. 44. 45. ...... 46. 47. ServiceDispatcherServiceConnection conn 48. Context context Handler activityThread int flags 49. mIServiceConnection new InnerConnectionthis 50. mConnection conn 51. mActivityThread activityThread 52. ...... 53. 54. 55. ...... 56. 57. IServiceConnection getIServiceConnection 58. return mIServiceConnection 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文件中 java view plaincopy 1. class ActivityManagerProxy implements IActivityManager 2. 3. ...... 4. 5. public int bindServiceIApplicationThread caller IBinder token 6. Intent service String resolvedType IServiceConnection connection 7. int flags throws RemoteException 8. Parcel data Parcel.obtain 9. Parcel reply Parcel.obtain 10. data.writeInterfaceTokenIActivityManager.descriptor 11. data.writeStrongBindercaller null caller.asBinder : null 12. data.writeStrongBindertoken 13. service.writeToParceldata 0 14. data.writeStringresolvedType 15. data.writeStrongBinderconnection.asBinder 16. data.writeIntflags 17. mRemote.transactBIND_SERVICE_TRANSACTION data reply 0 18. reply.readException 19. int res reply.readInt 20. data.recycle 21. reply.recycle 22. return res 23. 24. 25. ...... 26. 这个函数通过Binder驱动程序就进入到ActivityManagerService的bindService函数去了。
Step 6. ActivityManagerService.bindService 这个函数定义在frameworks/base/services/java/com/
android/server/am/ActivityManagerService.java文件中 java view plaincopy 1. public final class ActivityManagerService extends ActivityManagerNative 2. implements Watchdog.Monitor BatteryStatsImpl.BatteryCallback 3. ...... 4. 5. public int bindServiceIApplicationThread caller IBinder token 6. Intent service String resolvedType 7. IServiceConnection connection int flags 8. ...... 9. 10. synchronizedthis 11. ...... 12. final ProcessRecord callerApp getRecordForAppLockedcaller 13. ...... 14. 15. ActivityRecord activity null 16. if token null 17. int aindex mMainStack.indexOfTokenLockedtoken 18. ...... 19. activity ActivityRecordmMainStack.mHistory.getaindex 20. 21. 22. ...... 23. 24. ServiceLookupResult res 25. retrieveServiceLockedservice resolvedType 26. Binder.getCallingPid Binder.getCallingUid 27. 28. ...... 29. 30. ServiceRecord s res.record 31. 32. final long origId Binder.clearCallingIdentity 33. 34. ...... 35. 36. AppBindRecord b s.retrieveAppBindingLockedservice callerApp 37. ConnectionRecord c new ConnectionRecordb activity 38. connection flags clientLabel clientIntent 39. 40. IBinder binder connection.asBinder 41. ArrayListltConnectionRecordgt clist s.connections.getbinder 42. 43. if clist null 44. clist new ArrayListltConnectionRecordgt 45. s.connections.putbinder clist 46. 47. clist.addc 48. b.connections.addc 49. if activity null 50. if activity.connections null 51. activity.connections new HashSetltConnectionRecordgt 52. 53. activity.connections.addc 54. 55. b.client.connections.addc 56. clist mServiceConnections.getbinder 57. if clist null 58. clist new ArrayListltConnectionRecordgt 59. mServiceConnections.putbinder clist 60. 61. 62. clist.addc 63. 64. if flagsampContext.BIND_AUTO_CREATE 0 65. ...... 66. if bringUpServiceLockeds service.getFlags false 67. return 0 68. 69. 70. 71. ...... 72. 73. 74. return 1 75. 76. 77. ...... 78. 函数首先根据传进来的参数token是MainActivity在ActivityManagerService里面的一个令牌通过这个令牌就可以将这个代表MainActivity的ActivityRecord取回来了。
接着通过retrieveServiceLocked函数得到一个ServiceRecord这个ServiceReocrd描述的是一个Service对象这里就是CounterService了这是根据传进来的参数service的内容获得的。
回忆一下在MainActivity.onCreate函数绑定服务的语句 java view plaincopy 1. Intent bindIntent new IntentMainActivity.this CounterService.class 2. bindServicebindIntent serviceConnection Context.BIND_AUTO_CREATE 这里的参数service就是上面的bindIntent了它里面设置了CounterService类的信息CounterService.class因此这里可以通过它来把CounterService的信息取出来并且保存在ServiceRecord对象s中。
接下来就是把传进来的参数connection封装成一个ConnectionRecord对象。
注意这里的参数connection是一个Binder对象它的类型是LoadedApk.ServiceDispatcher.InnerConnection是在Step 4中创建的后续ActivityManagerService就是要通过它来告诉MainActivityCounterService已经启动起来了因此这里要把这个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文件中 java view plaincopy 1. public final class ActivityManagerService extends ActivityManagerNative 2. implements Watchdog.Monitor BatteryStatsImpl.BatteryCallback 3. ...... 4. 5. private final boolean bringUpServiceLockedServiceRecord r 6. int intentFlags boolean whileRestarting 7. ...... 8. 9. final String appName r.processName 10. ProcessRecord app getProcessRecordLockedappName r.appInfo.uid 11. 12. if app null ampamp app.thread null 13. try 14. realStartServiceLockedr app 15. return true 16. catch RemoteException e 17. ...... 18. 19. 20. 21. // Not running -- get it started and enqueue this service record 22. // to be executed when the app comes up. 23. if startProcessLockedappName r.appInfo true intentFlags 24. quotservicequot r.name false null 25. ...... 26. 27. 28. ...... 29. 30. 31. ...... 32. 回忆在
Android系统中的广播Broadcast机制简要介绍和学习计划中一文中我们没有在程序的AndroidManifest.xml配置文件中设置CounterService的process属性值因此它默认就为application标签的process属性值而application标签的process属性值也没有设置于是它们就默认为应用程序的包名了即这里的appName的值.
上一篇:
Android系统原理与开发要点详解 韩超 03_Android的Linux内核与驱动程序
下一篇:
电话销售英文简历范文