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小时内删除。