service组件二之创建绑定service(Bound Service)
Bound Service顾名思义,绑定服务。将service与其他组件更有甚于其他appication绑定,并且在service服务的过程中,进行交互。相比于简单的service,增加了交互功能。
简单来说,实现boundService,在service端,需要实现onBind()方法,同时在内部继承Binder类,只需要实现getService()方法即可。在客户端调用的时候,需要在其内部实现ServiceConnection接口,并且调用bindService()与service进行绑定。交互的数据封装在IBinder里面。
具体有三类,常用的是:
1.基于同进程的Extending the Binder class
2.使用Messenger(多进程间通信IPC)
具体步骤如下:
第一种方式:
1.创建TestBoundService
构造内部类继承Binder,重写其getService(),返回当前service对象;重写service 的onBind(),返回内部类对象;具体来说就是service封装进了binder。
package com.nankang.example.ad.apis;
import java.util.Random;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class TestBoundService extends Service{
private final IBinder ibinder = new TestBoundBinder();
private final Random ran = new Random();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return ibinder;
}
public class TestBoundBinder extends Binder{
TestBoundService getService(){
return TestBoundService.this;
}
}
public int getRandomNum(){
return ran.nextInt(100);
}
}
2.创建BoundServiceActivity
a).构造内部类,实现ServiceConnection接口,重写onServiceConnected和onServiceDisconnected,主要是至标志位以及获取service对象;
b).重写onStart(),onStop()方法,主要是绑定service以及解除绑定(bindService()和unbindService())。在这之前需要初始化内部类的实例。
c).通过service对象调用service中public的方法。
package com.nankang.example.ad.apis;
import com.nankang.example.ad.apis.TestBoundService.TestBoundBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class BoundServiceActivity extends Activity{
private TestBoundService testBoundService;
private boolean flag = false;
private TestConnection conn = new TestConnection();
private Button bt1 ;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.boundservice);
bt1 = (Button)findViewById(R.id.bound_bt1);
init();
}
/**
* 初始化button事件
*/
public void init(){
bt1.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
if(flag){
int num = testBoundService.getRandomNum();
Toast.makeText(BoundServiceActivity.this, "随机数是:"+num, Toast.LENGTH_LONG).show();
}
}
});
}
@Override
protected void onStart(){
super.onStart();
Intent service = new Intent(BoundServiceActivity.this,TestBoundService.class);
bindService(service, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop(){
super.onStop();
if(flag){
unbindService(conn);
flag = false ;
}
}
public class TestConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
TestBoundBinder tb = (TestBoundBinder)service;
testBoundService = tb.getService();
flag = true ;
}
@Override
public void onServiceDisconnected(ComponentName name) {
flag = false;
}
}
}
需要注意的是:这种方式并未涉及到进程通信。实现ServiceConnection接口,实际上是解锁操作,包括获取Ibinder对象,进而获取当前bound的service。
第二种方式(使用Messenger):
1.创建TestMessengerService
主要用到的类有:Messenger,Binder,Handler。三者之间的关系:handler通过Messenger的构造方法封装进了Messenger对象,然后是service和client之间通过binder来通信
a).创建handler的继承类,用来处理业务逻辑
b).实例化messenger,封装handler
c).在onBind方法中返回messenger的binder
package com.nankang.example.ad.apis;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
public class TestMessengerService extends Service implements FinaleFields{
final Messenger mMessenger = new Messenger(new MsgHandler());
class MsgHandler extends Handler{
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case msg_ok:
//Log.e("service 线程:", String.valueOf(Thread.currentThread().getId()));
Toast.makeText(getApplicationContext(), msg.getData().getString("info"), Toast.LENGTH_LONG).show();
break;
case msg_exit:
Toast.makeText(getApplicationContext(), "it' over!", Toast.LENGTH_LONG).show();
break;
default:
Toast.makeText(getApplicationContext(), "nothing ", Toast.LENGTH_LONG).show();
break;
}
}
}
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "prograss:"+Process.myPid(), Toast.LENGTH_LONG).show();
return mMessenger.getBinder();
}
}
2.创建BoundServiceAcitvity
a).构造内部类,实现ServiceConnection接口,获取service闯过来的messenger对象
b).重写onStart(),onStop()方法。
c).调用service具体的过程是,将信息封装进Message,然后通过messenger对象的send方法发送该Message对象到service,由service中的handleMessage方法处理。
package com.nankang.example.ad.apis;
import com.nankang.example.ad.apis.TestBoundService.TestBoundBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class BoundServiceActivity extends Activity implements FinaleFields{
private TestBoundService testBoundService;
private boolean flag = false;
private TestConnection conn = new TestConnection();
private Button bt1 ;
private Messenger mMessenger;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.boundservice);
bt1 = (Button)findViewById(R.id.bound_bt1);
init();
}
/**
* 初始化button事件
*/
public void init(){
bt1.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
// if(flag){
// Log.e("activity 线程:", String.valueOf(Thread.currentThread().getId()));
// int num = testBoundService.getRandomNum();
// Toast.makeText(BoundServiceActivity.this, "随机数是:"+num, Toast.LENGTH_LONG).show();
// }
if(flag){
Log.e("activity线程:", String.valueOf(Thread.currentThread().getId()));
Toast.makeText(getApplicationContext(), "activity prograss:"+Process.myPid(), Toast.LENGTH_LONG).show();
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("info","I'm coming from activity..");
msg.setData(bundle);
msg.what=msg_ok;
try {
mMessenger.send(msg);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
@Override
protected void onStart(){
super.onStart();
//Intent service = new Intent(BoundServiceActivity.this,TestBoundService.class);
Intent service = new Intent(BoundServiceActivity.this,TestMessengerService.class);
bindService(service, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop(){
super.onStop();
if(flag){
unbindService(conn);
flag = false ;
}
}
public class TestConnection implements ServiceConnection{
// @Override
// public void onServiceConnected(ComponentName name, IBinder service) {
// TestBoundBinder tb = (TestBoundBinder)service;
// testBoundService = tb.getService();
// flag = true ;
// }
public void onServiceConnected(ComponentName name, IBinder service){
mMessenger = new Messenger(service);
flag = true ;
}
@Override
public void onServiceDisconnected(ComponentName name) {
flag = false;
}
}
}
上面只是单方面的client向service发送消息,若是要client接收service发送的消息,同样可以在client初始化handler以及messenger对象,然后client向service发送消息的时候将messenger对象通过msg.replyTo封装进message对象中.
总结:
绑定到service需要经过以下几个步骤:
1.实现ServiceConnection接口
2.调用bindService方法
3.初始化service对象
4.释放service,调用unbindService().

浙公网安备 33010602011771号