1. 前言
本文的主要示例来自 3分钟带你看懂android中的Binder机制, 要实现binder通信,基本要实现如下的工作:
1.定义接口服务
是服务端要具备的能力来提供给客户端,定义一个接口继承IInterface,代表了服务端的能力
public interface PersonManger extends IInterface {
void addPerson(Person mPerson);
List<Person> getPersonList();
}
2. 定义Binder实体对象
Binder实体对象继承Binder,其次需要实现1中的服务接口。此Binder实体对象需要实现asInterface接口和onTransact接口。asInterface根据客户端是否位于同一进程返回实体对象或代理对象;onTransact()函数分析收到的数据包,调用相应的接口函数处理请求,这个函数的输入是来自Client的binder_transaction_data结构的数据包
public abstract class BinderObj extends Binder implements PersonManger {
public static final String DESCRIPTOR = "com.example.taolin.hellobinder";
public static final int TRANSAVTION_getPerson = IBinder.FIRST_CALL_TRANSACTION;
public static final int TRANSAVTION_addPerson = IBinder.FIRST_CALL_TRANSACTION + 1;
public static PersonManger asInterface(IBinder mIBinder){
IInterface iInterface = mIBinder.queryLocalInterface(DESCRIPTOR);
if (null!=iInterface&&iInterface instanceof PersonManger){
return (PersonManger)iInterface;
}
return new Proxy(mIBinder);
}
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code){
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
case TRANSAVTION_getPerson:
data.enforceInterface(DESCRIPTOR);
List<Person> result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(result);
return true;
case TRANSAVTION_addPerson:
data.enforceInterface(DESCRIPTOR);
Person arg0 = null;
if (data.readInt() != 0) {
arg0 = Person.CREATOR.createFromParcel(data);
}
this.addPerson(arg0);
reply.writeNoException();
return true;
}
return super.onTransact(code, data, reply, flags);
}
@Override
public IBinder asBinder() {
return this;
}
}
3. 定义代理对象
这里的代理对象实质就是client最终拿到的代理服务,它实现了1中的接口。client通过代理对象就可以和Server进行通信了,调用 remote.transact()将方法code,和data传输过去,对应的会回调在Server中的onTransact()中
public class Proxy implements PersonManger {
private IBinder mIBinder;
public Proxy(IBinder mIBinder) {
this.mIBinder =mIBinder;
}
@Override
public void addPerson(Person mPerson) {
Parcel data = Parcel.obtain();
Parcel replay = Parcel.obtain();
try {
data.writeInterfaceToken(DESCRIPTOR);
if (mPerson != null) {
data.writeInt(1);
mPerson.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mIBinder.transact(BinderObj.TRANSAVTION_addPerson, data, replay, 0);
replay.readException();
} catch (RemoteException e){
e.printStackTrace();
} finally {
replay.recycle();
data.recycle();
}
}
@Override
public List<Person> getPersonList() {
Parcel data = Parcel.obtain();
Parcel replay = Parcel.obtain();
List<Person> result = null;
try {
data.writeInterfaceToken(DESCRIPTOR);
mIBinder.transact(BinderObj.TRANSAVTION_getPerson, data, replay, 0);
replay.readException();
result = replay.createTypedArrayList(Person.CREATOR);
}catch (RemoteException e){
e.printStackTrace();
} finally{
replay.recycle();
data.recycle();
}
return result;
}
@Override
public IBinder asBinder() {
return null;
}
}
4. Server进程
onBind方法返回mStub对象,也就是Server中的Binder实体对象; 同时它要实现定义的接口
public class ServerSevice extends Service {
private static final String TAG = "ServerSevice";
private List<Person> mPeople = new ArrayList<>();
@Override
public void onCreate() {
mPeople.add(new Person());
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mStub;
}
private BinderObj mStub = new BinderObj() {
@Override
public void addPerson(Person mPerson) {
if (mPerson==null){
mPerson = new Person();
Log.e(TAG,"null obj");
}
mPeople.add(mPerson);
Log.e(TAG,mPeople.size()+"");
}
@Override
public List<Person> getPersonList() {
return mPeople;
}
};
}
5. 客户端进程
bindService传入一个ServiceConnection对象,在与服务端建立连接时,客户端bindService的onServiceConnected的回调里面,通过我们定义好的BinderObj的asInterface方法返回一个代理对象,再调用方法进行交互。asInterface方法中会调用queryLocalInterface,查找Binder本地对象,如果找到,说明Client和Server都在同一个进程,这个参数直接就是本地对象,直接强制类型转换然后返回,如果找不到,说明是远程对象那么就需要创建Binder代理对象,让这个Binder代理对象实现对于远程对象的访问
public class MainActivity extends AppCompatActivity {
private boolean isConnect = false;
private static final String TAG = "MainActivity";
private PersonManger personManger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start();
findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (personManger==null){
Log.e(TAG,"connect error");
return;
}
personManger.addPerson(new Person());
Log.e(TAG,personManger.getPersonList().size()+"");
}
});
}
private void start() {
Intent intent = new Intent(this, ServerSevice.class);
bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG,"connect success");
isConnect = true;
personManger = BinderObj.asInterface(service);
List<Person> personList = personManger.getPersonList();
Log.e(TAG,personList.size()+"");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG,"connect failed");
isConnect = false;
}
};
}