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 } };
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"); }
在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