AndroidService服务(三)——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在⼀个⽣命周期中只能被调⽤⼀次。详见:
三、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]
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. Create(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(it);
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 it:
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();
eclipse android61. 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. Destroy();
75.
76. if(sc != null){
77. unbindService(sc);
78. }
79. }
80. }
Service
[java]
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. Create();
21.
22. Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();
23. }
24.
25. @Override
26. public void onDestroy() {
27. Destroy();
28.
29. Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);
30. if(mediaPlayer != null){
31. mediaPlayer.stop();
32. lease();
33. }
34. }
35.
36.
37. public void play() {
38. if (mediaPlayer == null) {
39. mediaPlayer = ate(this, p);
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. }
[css]
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]
1. package ;
2.
3. interface IMusicControlService{
4. void play();
5. void stop();
6. void pause();
7. }
使⽤eclipse的Android插件,会根据这个aidl⽂件⽣成⼀个Java接⼝类,⽣成的接⼝类中会有⼀个内部类Stub类,Service来继承该Stub类:Service
[java]
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 = ate(RemoteMusicService.this, p);
16. mediaPlayer.setLooping(false);
17. }
18. if (!mediaPlayer.isPlaying()) {
19. mediaPlayer.start();
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论