当前位置: 代码迷 >> Android >> Android Service 服务(3)—— bindService与remoteService
  详细解决方案

Android Service 服务(3)—— bindService与remoteService

热度:77   发布时间:2016-05-01 10:45:21.0
Android Service 服务(三)—— bindService与remoteService

一、bindService简介

?

bindService是绑定Service服务,执行service服务中的逻辑流程。

service通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次stopService()方法便可以停止服务,无论之前它被调用了多少次的启动服务方法。

?

客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。

?

上面startService()和bindService()两种模式是完全独立的。你可以绑定一个已经通过startService()方法启动的服务。例如:一个后台播放音乐服务可以通过startService(intend)对象来播放音乐。可能用户在播放过程中要执行一些操作比如获取歌曲的一些信息,此时activity可以通过调用bindServices()方法与Service建立连接。这种情况下,stopServices()方法实际上不会停止服务,直到最后一次绑定关闭。

?

二、bindService启动流程

context.bindService()??——>?onCreate()??——>?onBind()??——>?Service running??——>?onUnbind()??——>?onDestroy()??——>?Service stop
?

onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。?

所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。详见:Android Service 服务(一)—— Service

?

三、bindService生命周期

?

像一个activity那样,一个service有些可以用来改变状态的生命周期方法,但是比activity的方法少,service生命周期方法只有三个public

???void onCreate()

???void onStart(Intent intent)

???void onDestroy()

通过实现这三个生命周期方法,你可以监听service的两个嵌套循环的生命周期:

1、整个生命周期

?service的整个生命周期是在onCreate()和onDestroy()方法之间。和activity一样,在onCreate()方法里初始化,在onDestroy()方法里释放资源。例如,一个背景音乐播放服务可以在onCreate()方法里播放,在onDestroy()方法里停止。

?

2、活动的生命周期

?service的活动生命周期是在onStart()之后,这个方法会处理通过startServices()方法传递来的Intent对象。音乐service可以通过开打intent对象来找到要播放的音乐,然后开始后台播放。注: service停止时没有相应的回调方法,即没有onStop()方法,只有onDestroy()销毁方法。

?

onCreate()方法和onDestroy()方法是针对所有的services,无论它们是否启动,通过Context.startService()和Context.bindService()方法都可以访问执行。然而,只有通过startService()方法启动service服务时才会调用onStart()方法

?

如果一个service允许别人绑定,那么需要实现以下额外的方法:

???????IBinder onBind(Intent intent)

???????boolean onUnbind(Intent intent)

???????void onRebind(Intent intent)

onBind()回调方法会继续传递通过bindService()传递来的intent对象

onUnbind()会处理传递给unbindService()的intent对象。如果service允许绑定,onBind()会返回客户端与服务互相联系的通信句柄(实例)。

如果建立了一个新的客户端与服务的连接,onUnbind()方法可以请求调用onRebind()方法。

?

记住: 任何服务无论它怎样建立,默认客户端都可以连接,所以任何service都能够接收onBind()和onUnbind()方法

?

?

四、bindService示例

Activity

?

[java]?view plaincopyprint?
?
  1. public?class?PlayBindMusic?extends?Activity?implements?OnClickListener?{??
  2. ??
  3. ????private?Button?playBtn;??
  4. ????private?Button?stopBtn;??
  5. ????private?Button?pauseBtn;??
  6. ????private?Button?exitBtn;??
  7. ??
  8. ????private?BindMusicService?musicService;??
  9. ??
  10. ????@Override??
  11. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  12. ????????super.onCreate(savedInstanceState);??
  13. ??
  14. ????????setContentView(R.layout.bind_music_service);??
  15. ??
  16. ????????playBtn?=?(Button)?findViewById(R.id.play);??
  17. ????????stopBtn?=?(Button)?findViewById(R.id.stop);??
  18. ????????pauseBtn?=?(Button)?findViewById(R.id.pause);??
  19. ????????exitBtn?=?(Button)?findViewById(R.id.exit);??
  20. ??
  21. ????????playBtn.setOnClickListener(this);??
  22. ????????stopBtn.setOnClickListener(this);??
  23. ????????pauseBtn.setOnClickListener(this);??
  24. ????????exitBtn.setOnClickListener(this);??
  25. ??
  26. ????????connection();??
  27. ????}??
  28. ??
  29. ????private?void?connection()?{??
  30. ????????Intent?intent?=?new?Intent("com.homer.bind.bindService");??
  31. ????????bindService(intent,?sc,?Context.BIND_AUTO_CREATE);??????????//?bindService??
  32. ????}??
  33. ??
  34. ????@Override??
  35. ????public?void?onClick(View?v)?{??
  36. ????????switch?(v.getId())?{??
  37. ????????case?R.id.play:??
  38. ????????????musicService.play();??
  39. ????????????break;??
  40. ????????case?R.id.stop:??
  41. ????????????if?(musicService?!=?null)?{??
  42. ????????????????musicService.stop();??
  43. ????????????}??
  44. ????????????break;??
  45. ????????case?R.id.pause:??
  46. ????????????if?(musicService?!=?null)?{??
  47. ????????????????musicService.pause();??
  48. ????????????}??
  49. ????????????break;??
  50. ????????case?R.id.exit:??
  51. ????????????this.finish();??
  52. ????????????break;??
  53. ????????}??
  54. ????}??
  55. ??
  56. ????private?ServiceConnection?sc?=?new?ServiceConnection()?{??
  57. ??
  58. ????????@Override??
  59. ????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{???????//connect?Service??
  60. ????????????musicService?=?((BindMusicService.MyBinder)?(service)).getService();??
  61. ????????????if?(musicService?!=?null)?{??
  62. ????????????????musicService.play();????????//?play?music??
  63. ????????????}??
  64. ????????}??
  65. ??????????
  66. ????????@Override??
  67. ????????public?void?onServiceDisconnected(ComponentName?name)?{?????????????????//disconnect?Service??
  68. ????????????musicService?=?null;??
  69. ????????}??
  70. ????};??
  71. ??????
  72. ????@Override??
  73. ????public?void?onDestroy(){??
  74. ????????super.onDestroy();??
  75. ??????????
  76. ????????if(sc?!=?null){??
  77. ????????????unbindService(sc);??
  78. ????????}??
  79. ????}??
  80. }??


Service

?

?

[java]?view plaincopyprint?
?
  1. public?class?BindMusicService?extends?Service?{??
  2. ??
  3. ????private?MediaPlayer?mediaPlayer;??
  4. ??
  5. ????private?final?IBinder?binder?=?new?MyBinder();??
  6. ??
  7. ????public?class?MyBinder?extends?Binder?{??
  8. ????????BindMusicService?getService()?{??
  9. ????????????return?BindMusicService.this;??
  10. ????????}??
  11. ????}??
  12. ??
  13. ????@Override??
  14. ????public?IBinder?onBind(Intent?intent)?{??
  15. ????????return?binder;??
  16. ????}??
  17. ??
  18. ????@Override??
  19. ????public?void?onCreate()?{??
  20. ????????super.onCreate();??
  21. ??????????
  22. ????????Toast.makeText(this,?"show?media?player",?Toast.LENGTH_SHORT).show();??
  23. ????}??
  24. ??
  25. ????@Override??
  26. ????public?void?onDestroy()?{??
  27. ????????super.onDestroy();??
  28. ??????????
  29. ????????Toast.makeText(this,?"stop?media?player",?Toast.LENGTH_SHORT);??
  30. ????????if(mediaPlayer?!=?null){??
  31. ????????????mediaPlayer.stop();??
  32. ????????????mediaPlayer.release();??
  33. ????????}??
  34. ????}??
  35. ??
  36. ??????
  37. ????public?void?play()?{??
  38. ????????if?(mediaPlayer?==?null)?{??
  39. ????????????mediaPlayer?=?MediaPlayer.create(this,?R.raw.tmp);??
  40. ????????????mediaPlayer.setLooping(false);??
  41. ????????}??
  42. ????????if?(!mediaPlayer.isPlaying())?{??
  43. ????????????mediaPlayer.start();??
  44. ????????}??
  45. ????}??
  46. ??
  47. ????public?void?pause()?{??
  48. ????????if?(mediaPlayer?!=?null?&&?mediaPlayer.isPlaying())?{??
  49. ????????????mediaPlayer.pause();??
  50. ????????}??
  51. ????}??
  52. ??
  53. ????public?void?stop()?{??
  54. ????????if?(mediaPlayer?!=?null)?{??
  55. ????????????mediaPlayer.stop();??
  56. ????????????try?{??
  57. ????????????????mediaPlayer.prepare();??????//?在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数??
  58. ????????????}?catch?(IOException?ex)?{??
  59. ????????????????ex.printStackTrace();??
  60. ????????????}??
  61. ????????}??
  62. ????}??
  63. }??


AndroidManifest.xml

?

?

[css]?view plaincopyprint?
?
  1. <service??
  2. ????android:name=".bind.BindMusicService"??
  3. ????android:enabled="true"?>??
  4. ????<intent-filter>??
  5. ????????<action?android:name="com.homer.bind.bindService"?/>??
  6. ????</intent-filter>??
  7. </service>??



?

五、代码解析

1、 Activity中,Intent intent = new Intent("com.homer.bind.bindService"); 构建一个service的action,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);绑定服务

2、 Activity中,通过private ServiceConnection sc = new ServiceConnection() 建立一个Service连接,onServiceConnected()获取Service实例,onServiceDisconnected()释放连接

3、 Service中,重载onBind(Intent intent)方法,返回Service实例(即BindMusicService)给Activity,然后执行onCreate()函数(注:bindService不执行onStart()函数)

4、 Activity中,通过返回的Service实例musicService,执行音乐播放的操作(play、pause、stop等)

?

?

六、Remote Service拓展

通常每个应用程序都在它自己的进程内运行,但有时需要在进程之间传递对象(IPC通信),你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在android平台中,一个进程通常不能访问其它进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在android为我们提供了AIDL工具可以来做这件事。
?
AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如在一个Activity中)访问另一个进程中(例如一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
?
要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:

IMusicControlService.aidl

?

[css]?view plaincopyprint?
?
  1. package?com.homer.remote;??
  2. ??
  3. interface?IMusicControlService{??
  4. ????????void?play();???
  5. ????????void?stop();???
  6. ????????void?pause();??
  7. }??
?
使用eclipse的Android插件,会根据这个aidl文件生成一个Java接口类,生成的接口类中会有一个内部类Stub类,Service来继承该Stub类:
Service
[java]?view plaincopyprint?
?
  1. public?class?RemoteMusicService?extends?Service?{??
  2. ??
  3. ????private?MediaPlayer?mediaPlayer;??
  4. ??
  5. ????@Override??
  6. ????public?IBinder?onBind(Intent?intent)?{??
  7. ????????return?binder;??
  8. ????}??
  9. ??
  10. ????private?final?IMusicControlService.Stub?binder?=?new?IMusicControlService.Stub()?{??
  11. ??
  12. ????????@Override??
  13. ????????public?void?play()?throws?RemoteException?{??
  14. ????????????if?(mediaPlayer?==?null)?{??
  15. ????????????????mediaPlayer?=?MediaPlayer.create(RemoteMusicService.this,?R.raw.tmp);??
  16. ????????????????mediaPlayer.setLooping(false);??
  17. ????????????}??
  18. ????????????if?(!mediaPlayer.isPlaying())?{??
  19. ????????????????mediaPlayer.start();??
  20. ????????????}??
  21. ????????}??
  22. ??
  23. ????????@Override??
  24. ????????public?void?pause()?throws?RemoteException?{??
  25. ????????????if?(mediaPlayer?!=?null?&&?mediaPlayer.isPlaying())?{??
  26. ????????????????mediaPlayer.pause();??
  27. ????????????}?????????????
  28. ????????}??
  29. ??
  30. ????????@Override??
  31. ????????public?void?stop()?throws?RemoteException?{??
  32. ????????????if?(mediaPlayer?!=?null)?{??
  33. ????????????????mediaPlayer.stop();??
  34. ????????????????try?{??
  35. ????????????????????mediaPlayer.prepare();??????//?在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数??
  36. ????????????????}?catch?(IOException?ex)?{??
  37. ????????????????????ex.printStackTrace();??
  38. ????????????????}??
  39. ????????????}??
  40. ????????}??
  41. ????};??
  42. ??????
  43. ????@Override??
  44. ????public?void?onDestroy()?{??
  45. ????????super.onDestroy();??
  46. ??????????
  47. ????????if(mediaPlayer?!=?null){??
  48. ????????????mediaPlayer.stop();??
  49. ????????????mediaPlayer.release();??
  50. ????????}??
  51. ????}??
  52. }??

客户端(Activity)应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:

?

Activity

?

[java]?view plaincopyprint?
?
  1. public?class?PlayRemoteMusic?extends?Activity?implements?OnClickListener?{??
  2. ??
  3. ????private?Button?playBtn;??
  4. ????private?Button?stopBtn;??
  5. ????private?Button?pauseBtn;??
  6. ????private?Button?exitBtn;??
  7. ??
  8. ????private?IMusicControlService?musicService;??
  9. ??
  10. ????@Override??
  11. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  12. ????????super.onCreate(savedInstanceState);??
  13. ????????setContentView(R.layout.remote_music_service);??
  14. ??
  15. ????????playBtn?=?(Button)?findViewById(R.id.play);??
  16. ????????stopBtn?=?(Button)?findViewById(R.id.stop);??
  17. ????????pauseBtn?=?(Button)?findViewById(R.id.pause);??
  18. ????????exitBtn?=?(Button)?findViewById(R.id.exit);??
  19. ??
  20. ????????playBtn.setOnClickListener(this);??
  21. ????????stopBtn.setOnClickListener(this);??
  22. ????????pauseBtn.setOnClickListener(this);??
  23. ????????exitBtn.setOnClickListener(this);??
  24. ??
  25. ????????connection();??
  26. ????}??
  27. ??
  28. ????private?void?connection()?{??
  29. ????????Intent?intent?=?new?Intent("com.homer.remote.remoteMusicReceiver");??
  30. ????????bindService(intent,?sc,?Context.BIND_AUTO_CREATE);??????????????//?bindService??
  31. ????}??
  32. ??
  33. ????@Override??
  34. ????public?void?onClick(View?v)?{??
  35. ??
  36. ????????try?{??
  37. ????????????switch?(v.getId())?{??
  38. ????????????case?R.id.play:??
  39. ????????????????musicService.play();??
  40. ????????????????break;??
  41. ????????????case?R.id.stop:??
  42. ????????????????if?(musicService?!=?null)?{??
  43. ????????????????????musicService.stop();??
  44. ????????????????}??
  45. ????????????????break;??
  46. ????????????case?R.id.pause:??
  47. ????????????????if?(musicService?!=?null)?{??
  48. ????????????????????musicService.pause();??
  49. ????????????????}??
  50. ????????????????break;??
  51. ????????????case?R.id.exit:??
  52. ????????????????this.finish();??
  53. ????????????????break;??
  54. ????????????}??
  55. ????????}?catch?(RemoteException?e)?{??
  56. ????????????e.printStackTrace();??
  57. ????????}??
  58. ????}??
  59. ??
  60. ????private?ServiceConnection?sc?=?new?ServiceConnection()?{??
  61. ????????@Override??
  62. ????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{???????//connect?Service??
  63. ????????????musicService?=?IMusicControlService.Stub.asInterface(service);??
  64. ????????}??
  65. ??
  66. ????????@Override??
  67. ????????public?void?onServiceDisconnected(ComponentName?name)?{?????????????????//disconnect?Service??
  68. ????????????musicService?=?null;??
  69. ????????}??
  70. ??
  71. ????};??
  72. ??????
  73. ????@Override??
  74. ????public?void?onDestroy(){??
  75. ????????super.onDestroy();??
  76. ??????????
  77. ????????if(sc?!=?null){??
  78. ????????????unbindService(sc);??????????????//?unBindService??
  79. ????????}??
  80. ????}??
  81. }??


Remote Service流程总结:

1、 Activity(客户端)中,Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");构建intent,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);绑定服务

2、 Activity(客户端)中,通过ServiceConnection()重载onServiceConnected()建立连接,获取Service.Stub实例;onServiceDisconnected()释放连接(与bindService类似)

3、 Service中,通过重载onBind(Intent intent) 返回Service.Stub实例,但Service.Stub类是由aidl文件生成的接口类中的一个内部类Stub类,Service来继承该Stub类

4、 Activity中,通过操作Service实例(musicService),执行音乐播放操作(play、pause、stop等)

?

源码下载

?

?

参考推荐:

Service?(android developer)

Android Service 服务(一)—— Service

Android Service 服务(二)—— BroadcastReceiver

android中service和aidl详细整理

Android Service AIDL

android笔记--Service与AIDL

  相关解决方案