public class Binder extends Object implements IBinder
IBinder
为远程对象制定了基础的接口方法,轻量级进程内与进程间IPC调用的核心部分。该类为抽象类,并且android建议通过继承 Binder去实现接口,而不是直接的去实现IBinder接口。
IBinder的核心方法是:
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
它与Binder中的onTransact方法对应,它允许你使用IBinder(客户端)、Binder( 服务端 )交互。
并且当客户端执行完transact()方法后并不会立刻回调,而是等待 服务端 onTransact()执行完毕后才会回调。
/** * Default implementation is a stub that returns false. You will want * to override this to do the appropriate unmarshalling of transactions. * * <p>If you want to call this, call transact(). */ protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (code == INTERFACE_TRANSACTION) { reply.writeString(getInterfaceDescriptor()); return true; } else if (code == DUMP_TRANSACTION) { ParcelFileDescriptor fd = data.readFileDescriptor(); String[] args = data.readStringArray(); if (fd != null) { try { dump(fd.getFileDescriptor(), args); } finally { try { fd.close(); } catch (IOException e) { // swallowed, not propagated back to the caller } } } // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } return true; } return false; }
进程A调用transact()方法,将Parcel发送给进程B,进程B接收到传入的Parcel后,调用Binder.onTransact()方法,并使用Parcel进行回复。在等待进程B回复的过程中,进程A是阻塞的。
绑定服务进行交互的几种方式
1.Extending the binder class
应用场景
Service 是Applicatin私有的,并且与Application运行在同进程中(比较普遍),因为该方式不支持进程间通讯。
创建Binder与Service:
public class LocalService extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random(); 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 getRandomNumber() { return mGenerator.nextInt(100); } }客户端调用:
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service;// 获取本地的IBinder对象句柄 mService = binder.getService();//通过IBinder句柄,获取Service的句柄 mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
2.Use Messenger
应用场景:
使用消息驱动,支持IPC(Interface Progress Communication)。
===Handler异步消息处理线程详解===
示例代码:
public class MessengerService extends Service { /** Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mMessenger = new Messenger(new IncomingHandler()); /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } }
public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean mBound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service);//如果服务连接成功,则将服务端IBinder对象传递至客户端,mMessenger.getBinder();的值也是这里被初始化的; mBound = true;//这样做的好处是,1)将IBinder的处理封装在Messenger类中,2)由IPC调用转为本地的异步线程处理 } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound = false; } }; public void sayHello(View v) { if (!mBound) return; // Create and send a message to the service, using a supported 'what' value Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } }
3.Use AIDL (Android Interface Define Language)
Android本身并不推荐使用AIDL,因为它需要支持多线程,使用它会使应用变得更复杂。
关于AIDL接口的定义:请查阅AIDL。
操作步骤:
1.新建xxx.aidl文件,定义接口;
2.Android AIDL工具将自动编译在Gen目录下生成对应的Java文件(使用Eclipse开发环境)。
package com.example.android; interface IServerServiceAidl{ void startServer(String command); void stopServer(); }
实际上完全可以手动去实现这部分内容(如下面),
相较于使用AIDL在Gen目录下自动生成的JAVA文件来说,本质上并无区别;
public interface IServerServiceAidl extends IInterface { /** Local-side IPC implementation stub class. */ public void startServer(String command) throws RemoteException; public void stopServer() throws RemoteException; }
public class Proxy implements IServerServiceAidl { private IBinder mRemote; Proxy(IBinder remote) { mRemote = remote; } @Override public IBinder asBinder() { return mRemote; } public String getInterfaceDescriptor() { return Stub.DESCRIPTOR; } @Override public void startServer(String command) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(Stub.DESCRIPTOR); _data.writeString(command); mRemote.transact(Stub.TRANSACTION_STARTSERVER, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void stopServer() throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(Stub.DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_STOPSERVER, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } }
public abstract class Stub extends Binder implements IServerServiceAidl { public static final String DESCRIPTOR = "IServerServiceAidl"; public static final int TRANSACTION_STARTSERVER = (IBinder.FIRST_CALL_TRANSACTION + 0); public static final int TRANSACTION_STOPSERVER = (IBinder.FIRST_CALL_TRANSACTION + 1); /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an IServerServiceAidl interface, generating a * proxy if needed. */ public static IServerServiceAidl asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof IServerServiceAidl))) { Log.d("debug", "Return :Local Binder Object"); return ((IServerServiceAidl) iin); } Log.d("debug", "Return :Remote Binder Proxy Object"); return new Proxy(obj); } @Override public IBinder asBinder() { return this; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_STARTSERVER: { data.enforceInterface(DESCRIPTOR); String _arg0; _arg0 = data.readString(); this.startServer(_arg0); reply.writeNoException(); return true; } case TRANSACTION_STOPSERVER: { data.enforceInterface(DESCRIPTOR); this.stopServer(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } }这里当使用到Binder时,将会先判断是否是本地的Binder,如果是本地的就直接使用了没有必要去远程ServiceManager去索取;
接下来就是通过Parcel交互数据的过程,这里需要校验下DESCRIPTOR,来判断请求者是否是真的想请求指定服务程序。
附上一些扩展阅读资料以帮助更好的理解Binder:
Android Binder RPC机制了解
点击下载 mDemo-Binder 机制学习资源