Android Binder通信机制学习(二)

上一篇,了解了一下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就可以被实例化。


你可能感兴趣的:(android,Binder)