您的位置:首页 > 移动开发 > Android开发

Android Binder通信机制学习(二)

2014-06-15 17:17 387 查看
上一篇,了解了一下Binder通信机制的基本框架。此篇将用一个示例来说明一个。非常感谢一位网上朋友的源码分享,博主还有更多精彩Android框架分析文章

添加Test模块服务,方法姑且定义一个为test。

(1)程序构成

编译binder程序需要链接binder动态链接库,应用开发环境下使用ndk编程是不能链接binder动态链接库的,故此需要在源码开发环境下。本实例在vendor目录下建立了子目录shuame,然后把工程目录放在该目录下。

程序由2个部分组成,一个binder service程序,一个测试binder service的client程序,对应的Android.mk如下所示:

LOCAL_PATH := $(call my-dir)

#生成binder service的服务端
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE    := TestServer
LOCAL_SRC_FILES := \
ITestService.cpp \
TestServer.cpp

LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

#生成binder service的测试client端
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE    := TestClient
LOCAL_SRC_FILES := \
ITestService.cpp \
TestClient.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)


(2)程序源代码构成

Test.h :包含需要用到的头文件,声明接口,定义操作枚举,声明binder引用类

ITestService.cpp: 接口类方法的实现

TestServer.cpp: 声明并实现binder实体类 ,启动binder服务,并在service manager里注册

TestClient.cpp: 声明并实现binder 引用类, 测试binder服务的client

1. 声明Service的接口ITestService(test.h)

// Binder Service 接口test声明
class ITestService : public IInterface
{
public:
DECLARE_META_INTERFACE(TestService); // declare macro
virtual void test()=0;
};

// 客户端服务端通讯使用
enum
{
TEST = IBinder::FIRST_CALL_TRANSACTION,
};
2.完成BpTestService的声明,test实现

声明:

// BpXXX继承IXXX,完成test接口的实现,通过remote()->transact()远程调用到BnXXX::onTransaction(){ cast TEST: xxxx;}
class BpTestService: public BpInterface<ITestService> {
public:
BpTestService(const sp<IBinder>& impl);
virtual void test();
};
实现:

IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");

void BpTestService::test()
{
printf("in the get Test\n");
Parcel data, reply;
data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
remote()->transact(TEST, data, &reply);
printf("send Print %d\n", reply.readInt32());
}


3. 完成BnTestService接口类的声明,实现

声明:

class BnTestService: public BnInterface<ITestService> {
public:
virtual status_t
onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0);
virtual void test() {
printf("Now get test\n");
}

};


实现onTransact()方法:

status_t BnTestService::onTransact(uint_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
switch (code) {
case TEST: {
printf("got the client msg\n");
CHECK_INTERFACE(ITest, data, reply);
test();
reply->writeInt32(100);
return NO_ERROR;
}
break;
default:
break;
}
return NO_ERROR;
}
4. 实现客户端Client

int main() {
/*获取service manager引用*/
sp<IServiceManager> sm = defaultServiceManager();
/*获取test service的binder接口对象*/
sp<IBinder> binder = sm->getService(String16("service.testservice"));
/*转为sp<ITestService>*/
sp<ITestService> cs = interface_cast<ITestService>(binder);
/*通过binder引用调用test方法*/
cs->test();
return 0;
}
5.实现Server端

int main() {
ProcessState::self();  //初始化单例
/*获取service manager的binder引用*/
sp<IServiceManager> sm = defaultServiceManager();
/*添加服务 注意字符串必须用String16类型*/
sm->addService(String16("service.testservice"), new BnTestService());
ProcessState::self()->startThreadPool(); //启动线程池
IPCThreadState::self()->joinThreadPool();//等待线程结束
return 0;
}
6.编译生成TestServer,TestClient,分别push到Andrlid设备中,修改权限,运行并测试

架构和Android上的多媒体播放框架有点不一样,完成播放接口能力放在了Client的类中,而整个多媒体服务MediaPlayerService则负责创建并管理这些Client客户端。

总之,XXXXX是继承BnXXXX,BnXXXX继承IXXXX,BnXXXX中继承IXXXX中的虚函数必须被实现后才能被实例化,通常是在XXXX中被实现,主要XXXX就可以被实例化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: