`

android播放器(music player)源码分析1-Service,Binder,ServiceConnection

 
阅读更多

Android SDK 提供了两种类型的 Service ,用于类似 *nix 守护进程或者 windows 的服务

1. 本地服务 Local Service :用于应用程序内部

2. 远程服务 Remote Service :用于 android 系统内部的应用程序之间

前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程式比如 Activity 所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序服用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

不需要和 Activitye 交互的本地服务

本地服务编写比较简单。首先,要创建一个 Service 类,该类继承 android Service 类。然后在 Activity 中的 onCreate onDestory 中分别执行以下语句开启服务和停止服务。

this .startService( new Intent( this , ServiceImpl. class ));

this .stopService( new Intent( this , ServiceImpl. class ));

需要和 Activity 交互的远程服务

上面的示例是通过 startService stopService 启动关闭服务的。适用于服务和 activity 之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用 bind unbind 方法。

具体做法是,服务类需要增加接口,比如 ServiceInterface ,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承 Binder 类并实现 ServiceInterface 接口。还有,就是要实现 Service onBind 方法,不能只传回一个 null 了。

android musicplayer 源码中 MediaPlaybackService 使用了以上的服务方式,针对该源码进行分析:

首先需要了解进程间通信、需要 AIDL (以及 Binder

关于 AIDL 的介绍在文档: docs/guide/developing/tools/aidl.html

关于 IBinder 的介绍在文档: docs/reference/android/os/IBinder.html

以及 Binder docs/reference/android/os/Binder.html

manifest Service 的语法,见 docs/guide/topics/manifest /service-element.html

以上转自 http://blog.csdn.net/saintswordsman/archive/2010/01/05/5130947.aspx

步骤一:建立 aidl 文件

通过 aidl.exe 会在 gen 中生成该 service 类,该类中的成员变量 stub 实现了以下功能:

extends Binder implements ServiceInterface,源码如下

Java代码
  1. interfaceIMediaPlaybackService
  2. {
  3. voidopenfile(Stringpath);
  4. voidopenfileAsync(Stringpath);
  5. voidopen(inint[]list,intposition);
  6. ...................//接口方法
  7. }

Java代码
  1. publicinterfaceIMediaPlaybackServiceextendsandroid.os.IInterface{
  2. /**生成binder类*/
  3. publicstaticabstractclassStubextendsandroid.os.Binderimplements
  4. com.android.mymusic.IMediaPlaybackService{
  5. privatestaticfinaljava.lang.StringDESCRIPTOR="com.android.mymusic.IMediaPlaybackService";
  6. /**Constructthestubatattachittotheinterface.*/
  7. publicStub(){
  8. this.attachInterface(this,DESCRIPTOR);
  9. }
  10. ...................
  11. ...................
  12. ...................//binder方法
  13. }
  14. publicvoidopenfile(java.lang.Stringpath)
  15. throwsandroid.os.RemoteException;
  16. ...................
  17. ...................//接口方法
  18. ...................
  19. }

步骤二:编写服务的实现类 MediaPlaybackService

Java代码
  1. publicclassMediaPlaybackServiceextendsService{
  2. ......
  3. @Override
  4. publicIBinderonBind(Intentintent){
  5. mDelayedStopHandler.removeCallbacksAndMessages(null);
  6. mServiceInUse=true;
  7. returnmBinder;
  8. }
  9. privatefinalIMediaPlaybackService.StubmBinder=newIMediaPlaybackService.Stub()
  10. {
  11. ...................//实现接口方法
  12. };
  13. }

步骤三:编写一个消费这个服务的 Activity MediaPlaybackActivity: (除此之外还有其他类)

Java代码
  1. publicclassMediaPlaybackActivityextendsActivityimplementsMusicUtils.Defs,
  2. View.OnTouchListener,View.OnLongClickListener
  3. {
  4. privateIMediaPlaybackServicemService=null;
  5. @Override
  6. publicvoidonStart(){
  7. super.onStart();
  8. ...................//其他代码
  9. if(false==MusicUtils.bindToService(this,serviecConnection)){
  10. //somethingwentwrong
  11. ...................//其他代码
  12. }
  13. privateServiceConnectionserviecConnection=newServiceConnection(){
  14. publicvoidonServiceConnected(ComponentNameclassname,IBinderobj){
  15. mService=IMediaPlaybackService.Stub.asInterface(obj);
  16. if(MusicUtils.sService==null){
  17. MusicUtils.sService=mService;
  18. ...................//其他代码
  19. }
  20. }
  21. publicvoidonServiceDisconnected(ComponentNameclassname){
  22. }
  23. };
  24. }
  25. //MusicUtils类:定义了播放器所需要的操作以及service和Activity之间的相互作用的操作
  26. publicclassMusicUtils{
  27. ...................//其他代码
  28. publicstaticbooleanbindToService(Contextcontext,ServiceConnectioncallback){
  29. context.startService(newIntent(context,MediaPlaybackService.class));
  30. ServiceBindersb=newServiceBinder(callback);
  31. sConnectionMap.put(context,sb);
  32. returncontext.bindService((newIntent()).setClass(context,
  33. MediaPlaybackService.class),sb,0);
  34. }
  35. ...................//其他代码
  36. }

需要注意:

远程服务往往不只是传递 java 基本数据类型。这时需要注意 android 的一些限制和规定:

以下转自 http://yangguangfu.javaeye.com/blog/699306

1. android 支持 String CharSequence

2. 如果需要在 aidl 中使用其他 aidl 接口类型,需要 import ,即使是在相同包结构下;

3. android 允许传递实现 Parcelable 接口的类,需要 import

4. android 支持集合接口类型 List Map ,但是有一些限制,元素必须是基本型或者上述三种情况,不需要 import 集合接口类,但是需要对元素涉及到的类型 import

非基本数据类型,也不是 String CharSequence 类型的,需要有方向指示,包括 in out inout in 表示由客户端设置, out 表示由服务端设置, inout 是两者均可设置。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics