Service 这个一搜一大把详细的介绍,这里就不多说了。 实质就是一种不用和用户交互,在后台运行的一种 服务。
Service 分为 绑定的 和 不绑定的。
不绑定的:简单说:就是当你启动service后,不去主动的 StopService() 它 或者 不在service中调用 stopSelf() 是不会停止的。
绑定的:简单说:当你的绑定组件 启动service后,组件解除 绑定,那么service就会销毁,当然允许多个组件绑定,直到没有组件绑定到service的时候,它就会销毁了。
下来看例子。不绑定的 我注释的代码写的很清楚,那个很简单。主要说下 绑定的service,界面就是由2个按钮 1个是绑定,1个是解除绑定。
MainActivity.java 界面
public class MainActivity extends Activity {
//用来绑定链接的
private ServiceConnection conn;
//判断是否已绑定
public boolean isBind = false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//当 service启动后,再次启动 service,不会调用oncreate方法了,而是直接调用onStartCommand 方法
/**
* 1.
* 平常简单的启动service的方法 startService
* 停止serviced的方法 stopService
* 这个的特点就是 没有绑定service,当启动service的这个activity消失后,service仍然存在,
* 想要停止 service 必须手动 stop
*
* //startService(new Intent())
* //stopService(name)
*/
/**
* 2. 绑定的(同一进程中)
*/
conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 当绑定时 会从这个回调接口得到 binder对象 通过binder对象绑定的
MainBinService.BinServiceBind sBinder = (MainBinService.BinServiceBind)service;
// 然后使用 binder对象的方法
System.out.println( "11 + 11 = " + sBinder.add(11,11));
System.out.println("sBinder.getService().toString()"+ sBinder.getBinServiceBind().toString());
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
//启动绑定button
((Button)this.findViewById(R.id.button1)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//BIND_DEBUG_UNBIND 这个flag 用于调试 BIND_AUTO_CREATE 默认使用的
MainActivity.this.bindService(new Intent(MainActivity.this, MainBinService.class),
conn,
Context.BIND_AUTO_CREATE);//这个flag 默认使用
isBind = true;
}
});
//解除绑定 button
((Button)this.findViewById(R.id.button2)).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(isBind){
// 多次调用 unbindService 会抛出异常
MainActivity.this.unbindService(conn);
}
}
});
}
public class MainBinService extends Service{
/**
*android:process ---------- 表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字
*android:enabled ---------- 如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false
*android:exported --------- 表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
*/
private BinServiceBind myBind;
//bind
public class BinServiceBind extends Binder{
public MainBinService getBinServiceBind(){
return MainBinService.this;
}
public int add(int a,int b){
return a+b;
}
}
// 返回binder 对象
@Override
public IBinder onBind(Intent arg0) {
return myBind;
}
@Override
public void onCreate() {
super.onCreate();
System.out.println(" SERVCEI oncreate = ");
myBind = new BinServiceBind();
}
@Override
public boolean onUnbind(Intent intent) {
// 所有的客户端使用unbindService()解除了绑定
return false;
}
@Override
public void onRebind(Intent intent) {
// 一个客户端在调用onUnbind()之后,正使用bindService()绑定到service
}
@Override
public void onDestroy() {
System.out.println(" service destory");
super.onDestroy();
}
/**
* 注意方法onStartCommand()必须返回一个整数.这个整数描述了在系统杀死它的事件中系统如何继续这个服务
* onStartCommand()返回值必须是下面常量之一:
START_NOT_STICKY
如果系统在onStartCommand()返回后杀死了服务,不要重新创建这个service,除非还有挂起的intent需要被传送.
这是避免在不必要时运行你的service和当你的应用可以简单重启任何未竟的工作时的最佳选择.
START_STICKY
如果系统在onStartCommand()返回后杀死了这个service,会重新创建这个service并且调用onStartCommand(),但是不再重新发送上次最后一个intent,
而是使用一个nullintent调用onStartCommand(),除非有一些挂起的intent,在此情况下,这些挂起的intent被派送.这适合于媒体播放器(or或相似也的服务),
它不执行命令,但是无限期的运行并等待一个工作.
START_REDELIVER_INTENT
如果系统在onStartCommand()返回后杀死了service,重新创建这个service并且使用上次最后一个intent调用onStartCommand().
任何挂起的intent都顺序地被派送.这适合于活跃地执行一个工作并且应被立即恢复的服务,比如下载一个文件.
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
当我点击activity 中的绑定按钮时(看到service oncreate 并且进入回调方法):
当点击activity中的解除绑定按钮时(进入到了service desroty 方法),
二,现在要实现 activity 和service间的相互通信
(xml 太过简单就不贴了,代码自己考过去画几个button 就可以测了呢 )当我点击 通信按钮。
上面第一张是,我点击通讯按钮后,进入到了service, 第2张是 service 处理完自己的事后(3秒后),给activity 返回的1个信息,并在activity中显示toast
要用到 Messenger(信使) 注释非常详细了,实质就是通过Messenger 对象然后进行消息的发送。
先来 HandlerActivity.java
public class HandlerActivity extends Activity {
//接收service的 Messenger
private Messenger serviceMessenger = null;
//activity本身 的 Messenger
private Messenger myMessenger =null ;
boolean mBound;
static final int service_back = 1;
//Handler
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what){
case service_back:
//当service 完成自己的事情后 通知activity 显示 toast
Toast.makeText(getApplicationContext(), "service back ==!", Toast.LENGTH_SHORT).show();
break;
}
};
};
/**
*与service的主接口交互的类
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// 当与service的连接已经建立时被调用,获得service 返回的 Ibinder对象
serviceMessenger = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// 当与service的连接意外断开时被调用-- 也就是,service的进程崩溃了
serviceMessenger = null;
mBound = false;
}
};
public void doSomethings() {
if (!mBound){
return;
}
myMessenger = new Messenger(handler);
// 创建并发送一个消息给service
Message msg = Message.obtain(null, HandlerService.Hello_Service, 0, 0);
//指明此message发送到何处的可选Messenger对象。具体的使用方法由发送者和接受者决定。
msg.replyTo = myMessenger;
try {
//将包含本身 Messenger 的 message发送出去
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//点击 activity的 button 给 service 发送消息 让其执行
((Button)this.findViewById(R.id.button3)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//调用sen message
doSomethings();
}
});
}
@Override
protected void onStart() {
super.onStart();
// 这个class 是为了测试通讯,所以启动的时候直接绑定到service
bindService(new Intent(this, HandlerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
HandlerService.java
public class HandlerService extends Service {
public static final int Hello_Service = 1;
// Handler处理
private Handler handler =new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Hello_Service:
//显示toast
Toast.makeText(getApplicationContext(), " Hello_Service_in_handler! ", Toast.LENGTH_SHORT).show();
//得到msg 就可以用 得到的 messenger 给客户端发送数据了
replyMessenger = msg.replyTo;
//执行相应的操作
th.start();
break;
default:
super.handleMessage(msg);
}
}
};
//使用 信息给客户端发送消息 发送消息的的对象
private final Messenger serviceMessenger = new Messenger(handler);
// 得到的客户端传递过来的 Messenger(信使)
private Messenger replyMessenger ;
//做了1个假的执行操作的线程
private Thread th = new Thread(){
public void run() {
try {
Thread.sleep(3000);
//假设上面执行了自己操作3秒
//现在给客户端回应
Message msg = Message.obtain(null, HandlerActivity.service_back, 0,0);
replyMessenger.send(msg);
} catch (RemoteException e) {
} catch (InterruptedException e) {
}
};
};
/**
* 当绑定到service,我们返回指向我们的messenger的接口
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return serviceMessenger.getBinder();
}
/**
* 当你需要执行IPC时,为你的接口使用一个Messenger比使用AIDL实现它简单,
* 因为Messenger把所有对service的调用入队列,一个纯AIDL接口并行发送请求到service,这样就必须用多线程来处理了.
对于大多数应用,service不需使用多线程,所以使用一个Messenger允许service在一个时刻只处理一个请求.
如果要使用多线程,那么就要使用到AIDL
*/
@Override
public void onCreate() {
super.onCreate();
}
/** Messenger:信使
官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。
该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,
客户端持有这个Messenger就可以与服务端通信了。
*
* 以前我们使用Handler+Message的方式进行通信,都是在同一个进程中,从线程持有一个主线程的Handler对象,并向主线程发送消息。
而Android既然可以使用bindler机制进行跨进行通信,所以我们当然可以将Handler与bindler结合起来进行跨进程发送消息。
查看API就可以发现,Messenger就是这种方式的实现。
*/
}
好了这个有点长了 AIDL的通信下个说 = =,