与此同时,ServiceManager还提供了addService,checkService两个重要方法,用来维护sCache列表登记的Service的名称以及引用。我们用一个图来描述这整个过程
通过上面的分析了解:客户端首先需要通过Binder的进程都需要先获得ServiceManager代理对象才能进行Binder通讯。所以,ServiceManager在C/C++层面提供服务代理,又在Java层面提供服务代理。
接着我们通过一个简单跨进程通讯Demo来加深对Binder的了解和使用。我们分三步:
1.设计服务端,新建 一个基于Binder的类。
2.设计客户端,获取远程Binder对象。
3.操作获取的Binder对象执行操作。
创建Service端
我们只要基于Binder类新建一个服务类即可。在设计这个客户端之前,我们要考虑两个问题:
a.客户端如何获得服务端的Binder的引用。
b.客户端和服务端必须事先约定好 服务端函数的参数在包裹中的顺序。
对于第一个问题,我们向一个本地的service类进行连接,在这个客户端与servcie建立连接后返回一个Binder,即我们设计的服务端。
对于第二个问题,Android中SDK中为我们提供了一个aidl工具,借着这个工具我们可以将aidl文件上转化为一个java类文件,在该java文件中,同时重载了transact和onTransact()方法,统一了存入包裹和读取包裹参数。
设计服务端
先看下工程目录,了解整个代码的构成
1)、创建一个IAidlBinder服务,这个服务里有两个服务函数,getInfo(),getFruit(),这里我们就编写一个IAidlBinder文件,代码如下:
package com.binderserver; import com.binderserver.Fruit; interface IAidlBinder{ String getInfo(); Fruit getFruit(); }1.java原子类型,如int,long,String等变量。
2.Binder引用。
3.实现了Parcelable的对象。
这里文件名称第一个"I"的含义是IIterface类,即这是一个可以提供远程服务的类。我们创建好文件后,aidi工具会以文件的名称在gen目录下生成一个java类。
接着看看aidl生成的IAidlBinder.java代码。
/* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\workspace\\BinderServer\\src\\com\\binderserver\\IAidlBinder.aidl */ package com.binderserver; public interface IAidlBinder extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.binderserver.IAidlBinder { private static final java.lang.String DESCRIPTOR = "com.binderserver.IAidlBinder"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.binderserver.IAidlBinder * interface, generating a proxy if needed. */ public static com.binderserver.IAidlBinder asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = (android.os.IInterface) obj .queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.binderserver.IAidlBinder))) { return ((com.binderserver.IAidlBinder) iin); } return new com.binderserver.IAidlBinder.Stub.Proxy(obj); } 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_getInfo: { data.enforceInterface(DESCRIPTOR); java.lang.String _result = this.getInfo(); reply.writeNoException(); reply.writeString(_result); return true; } case TRANSACTION_getFruit: { data.enforceInterface(DESCRIPTOR); Fruit _result = this.getFruit(); reply.writeNoException(); if ((_result != null)) { reply.writeInt(1); _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.binderserver.IAidlBinder { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } public java.lang.String getInfo() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getInfo, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } public Fruit getFruit() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); Fruit _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getFruit, _data, _reply, 0); _reply.readException(); if ((0 != _reply.readInt())) { _result = Fruit.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getFruit = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public java.lang.String getInfo() throws android.os.RemoteException; public Fruit getFruit() throws android.os.RemoteException; }