Android:让我们来写一写Binder
Posted bdmh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:让我们来写一写Binder相关的知识,希望对你有一定的参考价值。
Binder作为android中跨进程通信的一部分,在源码中是起了极其重要的作用。比如ActivityManagerService,就是通过Binder来控制Activity的操作。至于Binder的通信,很多文章都是通过创建AIDL工程,由工具自动生成代码,就会看到诸如Stub、Proxy等内部类,看的是一头雾水。所以要想明明白白的使用Binder,自己手写一遍,对理解是非常有效的。
以下以在两个进程间通信为例来写一个Binder。
客户端
首先定义一个接口,包括Binder标识,发送Transact消息,接口定义等。
public interface IMyManager extends IInterface
String DESCRIPTOR = "my.study.IMyManager";
int Transact_Hello = IBinder.FIRST_CALL_TRANSACTION + 0;
void hello() throws RemoteException;
再定义一个和Server端的的协议类。实现IMyManager接口。
public class MyProxy implements IMyManager
private IBinder binder;
public MyProxy(IBinder token)
binder = token;
@Override
public IBinder asBinder()
return binder;
public java.lang.String getInterfaceDescriptor()
return DESCRIPTOR;
@Override
public void hello() throws RemoteException
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeString("中国");
data.writeInt(100);
binder.transact(Transact_Hello,data,reply,0);
Log.e("服务端返回",reply.readString());
Log.e("服务端返回",reply.readInt()+"");
上面代码中的hello方法,将负责和Server端进行交互,将transact消息发送给Server端,data可以写入信息,由Server端接收,reply是由Server端填充数据,返回给客户端读取。
接下来定义一个Stub,名字可以随意。因为不考虑在客户端创建,所以在客户端一方,我们只保留一个方法,用来转化IBinder接口,如果确保服务不是本进程的话,只需要最后一句即可。
public abstract class MyManager extends Binder implements IMyManager
public static IMyManager asInterface(IBinder obj)
if (obj == null)
return null;
//取出指定描述的接口,判断是不是本进程的
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin != null && iin instanceof IMyManager)
return (IMyManager)iin;
//如果不是,new一个协议对象
return new MyProxy(obj);
在客户端如何使用呢?比如在Activity中,创建时,可以绑定Server端的服务。
private IMyManager myService;
private ServiceConnection serviceConnection;
serviceConnection = new ServiceConnection()
@Override
public void onServiceConnected(ComponentName name, IBinder service)
myService = MyManager.asInterface(service);
@Override
public void onServiceDisconnected(ComponentName name)
myService = null;
;
//com.mh.binderserver为服务端的包名,后面提到
Intent intent = new Intent("com.mh.binderserver.MyService");
//指明服务端包名
intent.setPackage("com.mh.binderserver");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
在Activity的按钮点击事件中写
try
myService.hello();
catch (RemoteException e)
e.printStackTrace();
这样,客户端的任务就完成了,下面我们看服务端。
服务端
首先,和客户端一样,先定义一个接口:
public interface IMyManager extends IInterface
String DESCRIPTOR = "my.server.IMyManager";
int Transact_Hello = IBinder.FIRST_CALL_TRANSACTION + 0;
和客户端不一样,这里就不需要Proxy类了。然后定义MyManager。
public class MyManager extends Binder implements IMyManager
public MyManager()
this.attachInterface(this,DESCRIPTOR);
@Override
public IBinder asBinder()
return this;
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
switch (code)
case Transact_Hello:
Log.e("客户端传来",data.readString());
Log.e("客户端传来",data.readInt()+"");
reply.writeString("北京");
reply.writeInt(200);
return true;
return super.onTransact(code, data, reply, flags);
因为在服务端要创建Binder,所以这里构造方法中,要附加指定标识的接口。类似于注册一样。onTransact就是Binder中最重要的用来接收各方信息的入口。data和reply对应客户端Proxy中hello方法中发送的data和reply。
因为客户端要bind一个Service,所以服务端需要有一个Service对象。
public class MyService extends Service
//创建上面的MyManager对象
private final MyManager binder = new MyManager();
@Override
public void onCreate()
super.onCreate();
@Override
public IBinder onBind(Intent intent)
return binder;
然后在AndroidManifest中声明这个Service。注意action的name,就是客户端绑定Service时的那个intent中的action名字,要一致。
<service android:name=".MyService">
<intent-filter>
<action android:name="com.mh.binderserver.MyService" />
</intent-filter>
</service>
服务端启动Service。
startService(new Intent(this,MyService.class));
先启动Server端,然后在打开客户端,点击客户端页面上的按钮,日志中就会显示:
com.mh.binderserver E/客户端传来: 中国
com.mh.binderserver E/客户端传来: 100
my.study E/服务端返回: 北京
my.study E/服务端返回: 200
至此一个Binder操作完成。这样,当你再次去看Activity启动过程时,对ActivityManagerService的理解可能就明了多了。
以上是关于Android:让我们来写一写Binder的主要内容,如果未能解决你的问题,请参考以下文章