绑定服务

服务的生命周期

与其他组件不同的是,Service不能自己主动运行,需要调用相应的方法来启动。
启动服务的方法是Context.startService()和Context.bindService()。使用不同的方法启动服务,服务的生命周期也会不同。
1、startService方式开启服务的生命周期
服务会执行onCreate()  onStartCommand()方法,服务处于运行状态,直到自身调用stopSelf()方法或者其他组件调用stopService()方法时服务停止,最终被系统销毁。
服务会长期的在后台运行,并且服务的状态与开启者的状态没有关系。
2、bindService方式开启服务的生命周期
服务会执行onCreate()  onBind()方法,服务处于绑定状态, 客户端通过unbindService()方法关闭连接,解除绑定时,系统将直接销毁服务。
服务与开启者的状态有关,当调用者销毁了,服务也会被销毁。
定义服务
绑定服务,需要重写onBind()方法,并且返回一个IBinder对象,该IBinder客户端再绑定服务成功后可以获取一个该对象,因此客户端可以通过IBinder来控制服务。IBinder是一个接口,一般我们不会直接实现该接口,而是会继承Binder类,Binder类实现了IBinder类。
其中PlayMusicBinder继承自Binder类,并且提供了三个接口,分别是播放音乐、暂停音乐以及停止播放;在onBind()方法中返回这样一个实例。播放音乐用到了MediaPlayer,音乐文件直接直接放在了res/raw/目录下。至此,服务端就完成了,主要工具就是编写一个Binder类提供给客户端操作的接口。
从上面可以看到,定义服务端主要包括两步:

扩展Binder类,实现接口
在onBind()方法返回一个IBinder实例
2.定义调用者(Activity)
在定义完服务端后,再来定义客户端,bindService方法中第二个参数是一个ServiceConnection接口,当服务连接成功以及失去连接时会分别回调两个方法。下面是Activity的定义:

private PlayMusicService.PlayMusicBinder musicBinder;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //在服务连接成功后保存PlayeMusicBinder对象,控制服务端
        musicBinder = (PlayMusicService.PlayMusicBinder) service;
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        musicBinder = null;
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_play_music);
}
@Override
protected void onStart() {
    super.onStart();
    bindService(new Intent(this, PlayMusicService.class), connection, Service.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(connection);
}
public void playMusic(View view) {
    if (musicBinder != null)
        musicBinder.play();
}
public void pauseMusic(View view) {
    if (musicBinder != null)
        musicBinder.pause();
}
public void stopMusic(View view) {
    if (musicBinder != null)
        musicBinder.stop();
}   }

从上面的代码可以看出,在onStart中绑定服务,一旦服务绑定成功,则保存PlayMusicBinder对象。界面上有三个按钮,分别是播放、暂停和停止,接下来就可以控制后台服务播放音乐了。
从上面可以看到,定义客户端主要有三步:

定义ServiceConnection对象,在onServiceConnect回调中保存IBinder对象
绑定服务
使用onServiceConnect回调中保存的IBinder对象操作Service
在服务中扩展Binder这种方式适用于服务端和客户端在同一个进程中,那么如果客户端和服务端在不同进程中,那么该如何实现了?也就是通常意义上的IPC,IPC的方式有很多,比如管道、共享内存、Socket等等,但是在Android中有一种特殊的机制:Binder机制。下面首先介绍Binder机制的两种表现形式,Messenger和定义AIDL接口。下面分别就这两种方法就行介绍。
Messenger
Messenger对Binder进行了封装,适用于服务端单线程的情况,因为服务端会定义一个Handler用于顺序处理客户端发送过来的Message,在服务的onBind中返回内部的Binder。
Messenger用于发送消息,Handler用于处理消息,一般我们使用服务端作为处理消息,所以服务端需要Messenger和Handler,并且在onBind方法中返回Messenger内部的Binder,这样客户端就可以根据绑定服务后得到Messenger,可看做是服务端的Messenger,然后就可以通过它来发送消息了;那么如果服务端会在处理完客户端的消息后回复客户端,并且客户端也需要处理这个消息,那么该如何实现呢?
根据上面的分析,既然服务端需要回复客户端,也就得拿到客户端的Messenger,然后客户端需要处理消息,也需要一个Handler,所以说客户端也需要一个Messenger和一个Handler。下面我们以一个例子来详细说明,客户端向服务端发送两个整形数,服务端将和返回给客户端。
本地服务通信和远程服务通信
在Android系统中,服务的通信方式有两种,一种是本地服务通信,一种是远程服务通信。
本地服务通信是指应用程序内部的通信,而远程服务通信是指两个应用程序之间的通信。使用这两种方式进行通信时必须满足一个前提,就是服务必须以绑定方式开启。
1、本地服务通信
2、远程服务通信

远程服务
注册文件配置:android:process=":remote"
和主线程分离;

服务销毁
如果启动服务:startService(),bindService(intent,conn,Service.BIND_AUTO_CREATE);同时都使用了,只单击某一个stopService,unbindService停止都不会调用onDestroy();必须这个停止方法都点击一次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值