Android == 简单的binder通信

    这个月初开始入职实习了,经过这几天的熟悉,大概了解了将来负责的方向了,然后就是开始学习。主要学习Android的Framwork一层,为上层的UI写一些接口封装,涉及到Android不同的service之间的通信,以及上层Java和底下native(C/C++)之间通信,也就是JNI技术(Java Native Interface的缩写)。

    刚开始给了一份binder的简单程序理解理解,昨天看了一天,没有什么头绪,今天看了一位大神的文章才有了写思路,文章我转载了,链接为:http://blog.csdn.net/hjf161105/article/details/79482549 。接下来我将讲述一下我对这一份简单的binder程序的理解,首先看一下整个的项目结构,如下图所示:

    这个目录结构是我这个测试模块的结构,最终还是需要放到Android源码结构中去编译的。这个目录中包含四个文件夹,分别是client、service、include和TestService。这里需要说明下TestService目录,其余三个目录都是一眼就是明白的,client是客户端程序,service是服务器程序,include是本项目中使用到的头文件,TestService目录其实是client和service之间通信binder处理的目录。

    我们先看下这两个头文件以及他们相对应的cpp文件:

TestService.h文件

#ifndef _TEST_SERVICE_
#define _TEST_SERVICE_

#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <cutils/atomic.h>
#include <binder/Parcel.h>
#include "ITestService.h"
namespace android {

	//具体的服务操作类,继承于BnTestService,由BnTestService代理,
	//可由客户端的代理BpTestService调用
	class TestService:public BnTestService {
		public:
			virtual void	print(String8 str);		//虚函数,实现BnTestService的接口
	};

}
#endif

ITestService.h

#ifndef _ITEST_SERVICE_
#define _ITEST_SERVICE_

#include <utils/Errors.h>  // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android {
	
	//一个抽象类,是接口,可以被客户端的代理和服务器的代理实现
	class ITestService:public IInterface 
	{
	public:
		//这个宏里面定义了asInterface(),在ITestService.cpp中的
		//IMPLEMENT_META_INTERFACE具体实现这个asInterface()
		DECLARE_META_INTERFACE( TestService );
		//纯虚函数,被不同的代理继承后实现不同的功能
		virtual void	print(String8 str) = 0;
	};

	//服务器的代理类,继承于BnInterface接口和ITestService接口,
	//此类还会调用其派生类的此基类ITestService中的print方法
	class BnTestService: public BnInterface<ITestService>
	{
	public:
		//接收到客户端BpTestService的通信请求,根据code命令来决定操作
		virtual status_t    onTransact( uint32_t code,				//操作的code命令
									const Parcel& data,				//客户端请求发送的数据包
									Parcel* reply,					//可能是用于返回的数据包
									uint32_t flags = 0 );			//标志位
	};
}

#endif

TestService.cpp

#define LOG_TAG "TestService"
#include <utils/Log.h>

#include "TestService.h"

namespace android {

	//TestService中print方法的具体实现
	void TestService::print(String8 str)
	{
		LOGI("TestService::print   %s...\n", str.string());
	}

}

ITestService.cpp

#define LOG_TAG "TestService"

#include <stdint.h>
#include <sys/types.h>

#include <binder/Parcel.h>
#include <binder/IMemory.h>
#include <utils/Errors.h> 

#include "ITestService.h"

namespace android {

	//定义的操作命令
	enum {
		PRINT = IBinder::FIRST_CALL_TRANSACTION,
	};

	//客户端的代理类,用于响应客户端对ITestService的print方法的请求
	class BpTestService: public BpInterface<ITestService>
	{
	public:
		//构造函数,首先在参数列表中将IBinder参数传递给BpInterface
		BpTestService( const sp<IBinder>& impl )
			: BpInterface<ITestService>( impl ) {
		}

		//实现了其基类ITestService的print方法,响应客户端的请求
		virtual void	print(String8 str) {
			LOGD( "BpTestService print\n" );
			Parcel data, reply;				//用于传递的数据data和返回的数据reply
			data.writeInterfaceToken( ITestService::getInterfaceDescriptor() );
			data.writeString8( str );
			remote()->transact( PRINT, data, &reply );		//请求通信
		}
	};

	//在这个宏里面具体实现了asInterface()这个函数,在这个函数里面有一个new Bp##INTERFACE(obj)
	//相当于在这个函数中把TestService转化成了它的父类BpTestService并返回
	IMPLEMENT_META_INTERFACE( TestService, "test.service" );

	//响应客户端代理类的请求
	status_t BnTestService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags )
	{
		switch( code ) {
			case PRINT:{						//得到的操作命令为定义的PRINT,做出相应判断
				CHECK_INTERFACE( ITestService, data, reply );
				LOGD( "BnTestService print\n" );
				print(data.readString8());		//调用其子类TestService的print方法
			}break;

			default:{							//code和定义的PRINT不匹配,交给BBinder处理
				return BBinder::onTransact( code, data, reply, flags );
			}break;
		}

		return NO_ERROR;
	}


}

    以上这四个文件其实就是binder通信的主要实现,客户端和服务器其实只需要调用一下接口就可以实现通信了。这四个文件这涉及到了几个类,乍一看其实挺绕的,我才采用了UML图的方式梳理了一下这几个类的关系:

这几个类其实很多都是内部封装了,对于客户端程序来说,只需要了解ITestService和BpTestService类,对于服务器来说也是一样,只需了解ITestService和BnTestService类。我在上述的程序中做了比较详细的注释,可能会有一些地方还不了解而导致注释错误,还请多多包涵。下面把服务器程序和客户端程序也展示一下:

服务器main_TestService.cpp:

#define LOG_TAG "TestService"

#include <sys/types.h>
#include <unistd.h>
#include <grp.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
#include "ITestService.h"
#include "TestService.h"

using namespace android;

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    	
    //获取servicemanager对象
    sp<IServiceManager> sm = defaultServiceManager();
    
    //向servicemanager添加service,TestService,取名为test.service
	sm->addService(String16("test.service"), new TestService());

    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

客户端程序test_TestService.cpp:

#define LOG_TAG "TestService"

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>

#include "ITestService.h"

using namespace android;

class TestServiceDeath:public IBinder::DeathRecipient
{
	public:
		virtual void binderDied(const wp<IBinder>& who)
		{
			LOGD("TestService died notification");
		}
};


int main(int argc, char** argv)
{
	sp<ProcessState> proc(ProcessState::self());
	ProcessState::self()->startThreadPool();

	sp<IBinder> binder = defaultServiceManager()->getService(String16("test.service"));


	sp<TestServiceDeath> dethNotify = new TestServiceDeath();
	binder->linkToDeath( dethNotify );


	if ( binder != NULL ) {
	//interface_cast<ITestService>(binder) 直接把IBinder类型对象binder转化成了ITestService
	sp<ITestService> testServiceProxy = interface_cast<ITestService>( binder );
	testServiceProxy->print(String8("hello world"));
	}

	IPCThreadState::self()->joinThreadPool();
	return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值