Android Service
2020-06-07 本文已影响0人
二旬一月
生命周期
service生命周期.png默认情况下同进程使用
-
通过StartService启动Service
startService() --> onCreate --> onStartCommand() --> stopService --> onDestroy()
- 多次startService不会重复执行onCreate回调,但每次都会执行onStartCommand回调
-
通过bindService启动Service
bindService() --> onCreate() --> onBind() --> unbindService() --> onUnbind() --> onDestroy()
- bindService启动的服务和调用者之间是典型的client-server模式
- 当没有任何client与Service绑定时,Service会自行销毁
注意事项
- service 不是运行在子线程当中的,如果有耗时操作需要开启子线程,否则会引起ANR。
- service 是四大组件之一,使用之前必须在清单文件中进行注册。
<service android:name=".myservice"
android:enabled="true"
android:exported="true"
android:icon="@drawable/background_blue"
android:label="string"
android:process="string"
android:permission="string">
</service>
android:exported 表示是否允许除了当前程序之外的其他程序访问这个服务
android:enabled 表示是否启用这个服务
android:permission 是权限声明
android:process 是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。
android:isolatedProcess 设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。
- onDestroy() 当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。
代码示例
startService 模式
public class StartService extends Service {
private static final String TAG = "StartService";
private boolean running = false;
public StartService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG,"==StartService is start with onCreate==");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"==StartService is onStart with onStartCommand==");
running = true;
new Thread(){
@Override
public void run() {
super.run();
while (running){
Log.e(TAG,"StartService is running");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"==StartService is stop with onDestroy==");
running = false;
}
}
启动和停止服务
findViewById(R.id.buttonstart).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//启动服务
startService(new Intent(MainActivity.this,StartService.class));
}
});
findViewById(R.id.buttonstop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//关闭服务
stopService(new Intent(MainActivity.this,StartService.class));
}
});
bindService模式
public class BindService extends Service {
private static final String TAG = "BindService";
private long beginTime;
//2.初始化Binder对象
private MyBinder binder = new MyBinder();
//1.创建Binder类,并且提供返回该服务的方法,client 可以通过Binder获取Service实例
public class MyBinder extends Binder{
public BindService getService(){
return BindService.this;
}
}
//3.将binder返回给client
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"BindService is onBind");
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG,"BindService is onUnbind");
return super.onUnbind(intent);
}
public BindService() {
}
@Override
public void onCreate() {
super.onCreate();
beginTime = System.currentTimeMillis();
Log.e(TAG,"BindService is onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"BindService is onDestroy");
// beginTime = 0;
}
public long getRunningTime() throws Exception {
if (beginTime == 0){
throw new Exception("BindService is not bind!!");
}
return System.currentTimeMillis() - beginTime;
}
}
绑定和解绑
private BindService bindService;
//1. 创建ServiceConnection,用于接收service返回的Binder对象
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("MainActivity","onServiceConnected");
//得到Binder对象,并且通过getService()方法获取到service
BindService.MyBinder myBinder = (BindService.MyBinder)service;
bindService = myBinder.getService();
}
//Android 系统会在与服务的连接意外中断时调用该方法,当客户端取消绑定时不会调用该方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("MainActivity","onServiceDisconnected");
}
};
findViewById(R.id.buttonbind).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,BindService.class);
intent.putExtra("name","MainActivity");
//绑定服务
bindService(intent,connection,BIND_AUTO_CREATE);
}
});
findViewById(R.id.buttonunbind).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//解除绑定
unbindService(connection);
}
});
//完成绑定后,便可以在client中使用服务中的方法了。
long getServiceRunningTime() throws Exception {
return bindService.getRunningTime();
}
跨进程使用
简单的使用方式Message
- 服务实现一个 Handler,由其接收来自客户端的每个调用的回调
- Handler 用于创建 Messenger 对象(对 Handler 的引用)
- Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端
- 客户端使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用Messenger将 Message 对象发送给服务
- 服务在其 Handler 中(在 handleMessage() 方法中)接收每个 Message
代码示例
这里 MessengerService 服务是运行在另一个进程的。
<service
android:name=".MessengerService"
android:enabled="true"
android:exported="true"
android:process=":another"/>
public class MessengerService extends Service {
private static final String TAG ="MessengerService";
public MessengerService() {
}
// 定义一个内部类集成Hanlder 用于接收client 发送过来的数据
class MyHanlder extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
Log.e(TAG,"message is "+msg.what);
break;
case 2:
break;
default:
super.handleMessage(msg);
}
}
}
// 创建 Messenger ,传入Hanlder 实例对象
final Messenger mMessenger = new Messenger(new MyHanlder());
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"MessengerService is bind");
return mMessenger.getBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG,"MessengerService is Create");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"MessengerService is Destroy");
}
}
绑定和通讯代码
private boolean isBind = false;
private Messenger mMessenger;
private ServiceConnection connection_messenger = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//通过服务端传递的IBinder对象,创建相应的Messenger,
//并且通过这个IBinder 进行通讯
mMessenger = new Messenger(service);
Log.e("MainActivity","connection_messenger --》 onServiceDisconnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
findViewById(R.id.messenger).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(new Intent(MainActivity.this, MessengerService.class), connection_messenger,
BIND_AUTO_CREATE);
isBind = true;
}
});
findViewById(R.id.sendmsg).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isBind) return;
// 创建与服务交互的消息实体Message
Message msg = Message.obtain(null, 1, 0, 0);
try {
//发送消息
mMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.messenger_unbind).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isBind){
unbindService(connection_messenger);
isBind = false;
}
}
});
注意事项
在Messenger中进行数据传递必须将数据封装到Message中,Message可以传递的信息载体有,what,arg1,arg2,Bundle以及replyTo,至于object字段,对于同一进程中的数据传递确实很实用,但对于进程间的通信,则显得相当尴尬,在android2.2前,object不支持跨进程传输,但即便是android2.2之后也只能传递android系统提供的实现了Parcelable接口的对象,也就是说我们通过自定义实现Parcelable接口的对象无法通过object字段来传递,因此object字段的实用性在跨进程中也变得相当低了。不过所幸我们还有Bundle对象,Bundle可以支持大量的数据类型。
有时候我们可能还需要服务端能回应客户端,这时便需要提供双向消息传递了
示例
//用于接收服务器返回的信息
private Messenger mRecevierReplyMsg= new Messenger(new ReceiverReplyMsgHandler());
private static class ReceiverReplyMsgHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//接收服务端回复
case 2:
Log.e("MainActivity", "MessengerService 返回数据:"+msg.getData().getString("msg"));
break;
default:
super.handleMessage(msg);
}
}
}
发送数据时的修改
findViewById(R.id.sendmsg).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isBind) return;
//单向
// 创建与服务交互的消息实体Message
// Message msg = Message.obtain(null, 1, 0, 0);
// try {
// //发送消息
// mMessenger.send(msg);
// } catch (RemoteException e) {
// e.printStackTrace();
// }
//双向
// 创建与服务交互的消息实体Message
Message msg = Message.obtain(null, 2, 0, 0);
//把接收服务器端的回复的Messenger通过Message的replyTo参数传递给服务端
msg.replyTo=mRecevierReplyMsg;
try {
//发送消息
mMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
MessengerService 做一下修改
// 定义一个内部类集成Hanlder 用于接收client 发送过来的数据
class MyHanlder extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
Log.e(TAG,"message is "+msg.what);
break;
case 2:
Log.e(TAG,"message is "+msg.what);
//回复客户端信息,该对象由客户端传递过来
Messenger client=msg.replyTo;
//获取回复信息的消息实体
Message replyMsg=Message.obtain(null,2);
Bundle bundle=new Bundle();
bundle.putString("msg","返回数据");
replyMsg.setData(bundle);
//向客户端发送消息
try {
client.send(replyMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
通过Messenger 实现服务之间通讯的图解
MessengerService.png