Service(服务)是一种可以在后台执行长时间运行操作而没有用户界面的应用组件,是四大组件之一。
Service可以理解为没有专属界面(UI)的Activity。通过Service可以使程序在退出之后仍然能够对事件或用户操作做出反应,或者在后台继续运行某些程序功能。不同的是Activity拥有前台运行的用户界面,而Service不能自己运行,需要通过某个Activity或者其他Context对象来调用。
Service是由其他Service,Activity或者Broadcast Receiver开始,停止和控制。
比如后台播放音乐,后台更新下载。
用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
这种模式的Service无法进行通信以及数据交换。
此处不详细介绍。
通过Context.bindService()方法启动服务,再通过Context.unbindService()关闭服务。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
在activity中通过transact发送数据,在service中通过onTransact获取数据并返回数据,实现通信以及交流。
<service android:name=".MusicService" android:exported="true"/>
onTransact函数就是接收activity(或者其他组件)发来的信息,code是判断是谁发来,目的是什么,这个可自由设计。data是传过来的数据,可以通过data.readString()等(类型有很多,也有data.readInt()…)来获得数据,如果你在传输数据的时候并没有写入相应的数据,比如你并没有writeInt,但却使用了readInt,那读出来的会是0(null)。**注意:你可以连续写入,再连续读取,但只能一一对应,写一次只能读一次,因此,如果你需要重复使用data.readString(),可以先存到一个临时变量,再用这个变量来进行你需要的操作。**reply是回传给activity的数据,原理与data一样。
public class MyBinder extends Binder {
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code) {
//service solve
case 0:
reply.writeInt(1);
break;
//...
}
return super.onTransact(code, data, reply, flags);
}
}
声明定义一个MyBinder对象,MyBinder就是前一步继承Binder的新类。并在onBinder中返回这个对象,之所以要返回这个,是因为要在activity中获得这个binder对象,然后利用这个来和service通信。
public final IBinder binder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
在进行下面的操作之后,activity的binder并不能直接使用,还得继续绑定。
//在activity声明一个Binder对象,用来获取service里的binder
IBinder binder = new Binder();
//重写下面这个
private ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
binder = iBinder;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
写在oncreat函数中,Intent第二个参数是你写的Service类名字,执行这两条语句,就创建了一个service,如果你在service的初始化了一些数据,比如进行音乐播放或下载,那在这一步就会开始。之后就可以通过通信来控制service。
//Activity启动时绑定Service:
Intent intent = new Intent(this, MyService.class);
bindService(intent, sc, BIND_AUTO_CREATE);
在activity内使用transact发送数据,其中,注意int num = reply.readInt();
,只要调用了binder.transact(0, data, reply, 0);
,reply内马上就有了数据,这是在service里面写进去的。
注意:data和reply还是跟刚刚说的一样,写一次只能读一次,如果要重复使用,需要用一个临时变量来存数据。num在这里就是这个作用。
Parcel data = Parcel.obtain();
//你可以在这里用write写数据
data.writeString("test");//这样在service里就可以通过read来获取数据
Parcel reply = Parcel.obtain();
try {
binder.transact(0, data, reply, 0); //第一个参数可以随意改,只要在service有对应case就行
}catch (RemoteException e) {
e.printStackTrace();
}
int num = reply.readInt();
unbindService(sc);
这样子我们就完成了如何启动activity以及在service和activity中通信的功能。