关于Binder原理这里不做介绍了,可以参看Android技术内幕,但是关于Binder应用讲解的很详细的不多,因我在做一个移植的项目,与media类似,故研究了一下media,特别对其中的如何实现客户端、服务端才能通过Binder通信进行学习,总结如下:
1、基于接口编程,这是编程的趋势,好处实在太多
2、使得接口支持Binder,需要2步:
2.1定义接口,继承IInterface,并添加DECLARE_META_INTERFACE,并定义服务端接口,如下所示:
class IClient: public IInterface
{
public:
DECLARE_META_INTERFACE(Client);
virtual long Add(long a,long b) = 0;
};
class BnClient:public BnInterface<IClient>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
2.2 实现客户端和服务端
#define LOG_TAG "IClient"
//#define LOG_NDEBUG 0
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <IClient.h>
namespace android {
enum {
ADD = IBinder::FIRST_CALL_TRANSACTION
};
class BpClient : public BpInterface<IClient>
{
public:
BpClient(const sp<IBinder>& impl)
: BpInterface<IClient>(impl)
{
}
virtual long Add(long a,long b)
{
Parcel data,reply;
data.writeInterfaceToken(IClient::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
remote()->transact(ADD,data,&reply);
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(Client, "android.test.IClient");
// ----------------------------------------------------------------------
status_t BnClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case ADD:
{
CHECK_INTERFACE(IClient, data, reply);
reply->writeInt32(Add(data.readInt32(),data.readInt32()));
return NO_ERROR;
};
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android
3、最后在服务端实现具体类,继承BnClient