Android之Binder设计分析(2)

与此同时,ServiceManager还提供了addService,checkService两个重要方法,用来维护sCache列表登记的Service的名称以及引用。我们用一个图来描述这整个过程

Android之Binder设计分析

通过上面的分析了解:客户端首先需要通过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()方法,统一了存入包裹和读取包裹参数。

设计服务端

先看下工程目录,了解整个代码的构成

Android之Binder设计分析

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;  }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pfsgf.html