bind service可以实现应用组件绑定本地的service,也可以绑定其他应用的service,在android中每个
应用运行在自己的虚拟机中,每个虚拟机对应linux内核中一个进程,所以绑定其他应用的service,可以实
现进程间通信。
binder是能进行远程操作的对象的一个基类,一个轻量级的远程过程调用机制,核心部分在IBinder类
中定义。这个类是一个IBinder类的实现,为创建一个本地实现对象提供了标准的支持,后面的绑定都是
基于binder来实现。
绑定本地的service并与之交互相对比较简单,在service中创建一个binder实例,此实例中需要有一个
public方法可供绑定者调用,在此public 方法中返回service实例,这样就可以调用service中的public方法
了。binder实例通过onBind回调方法返回给绑定者:
public class LocalService extends Service {
private final IBinder mBinder = new LocalBinder();
private final int mserviceparam=10;
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getServiceParem(){
return mserviceparam;
}
}
绑定service通过以下方法实现:
bindService (Intent service, ServiceConnection conn, int flags)
ServiceConnection类中有两个回调方法,当service绑定成功后和取消绑定会调用这两个方法:
private ServiceConnection mConnection=new ServiceConnection (){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
绑定不同应用的service并与之交互,需要借助其他的类来实现,有两种方式:messenger 、aidl
1.messenger 中文翻译“信使”,负责信息的发送,可以跨进程,
messenger有两个构造函数:
a . public Messenger (Handler target)
handler是用来处理Messenger发送过来的message,
即一个Messenger会有一个Handler与之相对应,
通过Messenger.getBinder()获得一个binder对象,在service的onBind()方法中返回给客服端
public class MyService extends Service{
static final int MSG_SEND_FROM_REMOTE=1;
static final int MSG_SEND_FROM_LOCAL=2;
static final int MSG_RELY_FROM_SERVICE=3;
class IncomingHandler extends Handler{
public void handleMessage(Message msg){
switch(msg.what){
case MSG_SEND_FROM_REMOTE:
Toast.makeText(getApplicationContext(),"hello,i am from remote,send content is"+msg.getData().getString("sendContent"), Toast.LENGTH_LONG).show();
try {
msg.replyTo.send(Message.obtain(null, MSG_RELY_FROM_SERVICE, null));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case MSG_SEND_FROM_LOCAL:
Log.d("remoteservice", "MSG_SEND_FROM_LOCAL");
Toast.makeText(getApplicationContext(),"hello,i am from local", Toast.LENGTH_LONG).show();
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger=new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mMessenger.getBinder();
}}
b. public Messenger (IBinder target)
此构造函数一般用于绑定Service的组件中, 传入的binder对象是从service返回的,这样此Messenger
就会与service中的messenger相对应,用此Messenger发送消息,在service中可以接受到,并做相应处理。
到此我们只实现了从绑定组件发送消息到service,service不能发送消息给绑定组件,
如要实现双向通信,则需要在绑定组件中再创建一个Messenger对象,用public Messenger (Handler target)
构造方法,把此Messenger赋值给msg.replyTo,一并发送到service中,service用此Messenger发送消息给
绑定组件
private ServiceConnection mConnection=new ServiceConnection (){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mMessenger=new Messenger(service);//用service中返回的binder构建实例
send.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mMessenger=null;
send.setEnabled(false);
}
};
class incomingHandler extends Handler{ //构建绑定组件的handler,service发送过来的message在此处理
public void handleMessage(Message msg){
switch(msg.what){
case MSG_RELY_FROM_SERVICE:
sendcontent.setText("service received");
break;
default:
super.handleMessage(msg);
}
}
}
private Messenger reMessenger=new Messenger(new incomingHandler());//构建绑定组件的Messenger
private void sendMessage() throws RemoteException{//发送消息
Message msg=Message.obtain(null, MSG_SEND_FROM_REMOTE, null);
Bundle data=new Bundle();
data.putString("sendContent",sendcontent.getText().toString());
msg.setData(data);
msg.replyTo=reMessenger;
mMessenger.send(msg);
Log.d("remoteservice", "sendMessage");
}
2.AIDL android interface definition language 接口定义语言,
在src/ 目录中创建一个以.aidl为后缀名的接口定义文件,android SDK工具会自动在 gen/ 目录中创建
名字一样的java文件,java文件是一个Ibinder接口文件。
如定义的.aidl文件为:
package txj.remoteservice;
interface IRemoteService {
void showResult();
}
会自动生成一个.java 文件:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: E:\\android\\newworkspase\\RemoteService\\src\\txj\\remoteservice\\IRemoteService.aidl
*/
package txj.remoteservice;
public interface IRemoteService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements txj.remoteservice.IRemoteService
{
private static final java.lang.String DESCRIPTOR = "txj.remoteservice.IRemoteService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an txj.remoteservice.IRemoteService interface,
* generating a proxy if needed.
*/
public static txj.remoteservice.IRemoteService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof txj.remoteservice.IRemoteService))) {
return ((txj.remoteservice.IRemoteService)iin);
}
return new txj.remoteservice.IRemoteService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_showResult:
{
data.enforceInterface(DESCRIPTOR);
this.showResult();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements txj.remoteservice.IRemoteService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void showResult() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_showResult, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_showResult = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void showResult() throws android.os.RemoteException;
}
其中的stub抽象内部类继承了binder和实现了自己定义的接口
在service中需创建一个类extends Stub 并实现自己定义的接口方法,在onbind()方法中返回一个
此类的对象。
public class AidlService extends Service {
private IRemoteService.Stub mbindder=new IRemoteService.Stub() {
@Override
public void showResult(){
// TODO Auto-generated method stub
//Toast.makeText(AidlService.this, "the toast show from AidlService", Toast.LENGTH_LONG).show();
Log.d("remoteservice","showResult");
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mbindder;
}
public void onDestroy(){
Log.d("remoteservice","onDestroy");
super.onDestroy();
}
}
把此.aidl文件复制到需要绑定此服务的应用的src/ 文件目录中(包名也要一样),也会在gen/中自动生成
相对应的java文件。
绑定组件在绑定成功后会得到service返回的binder,通过下面方法得到自己定义接口类型的对象,即可
调用service中实现的方法:mAidlService=IRemoteService.Stub.asInterface(service);
实现代码:
private ServiceConnection mAidlConnection=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mAidlService=IRemoteService.Stub.asInterface(service);
Log.d("ConMainActivity", "onServiceConnected");
try {
mAidlService.showResult();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
源码下载地址:
http://download.csdn.net/detail/txj8612/5423099