这个月初开始入职实习了,经过这几天的熟悉,大概了解了将来负责的方向了,然后就是开始学习。主要学习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
#include
#include
#include
#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 // for status_t
#include
#include
#include
#include
#include
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
{
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
#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
#include
#include
#include
#include
#include "ITestService.h"
namespace android {
//定义的操作命令
enum {
PRINT = IBinder::FIRST_CALL_TRANSACTION,
};
//客户端的代理类,用于响应客户端对ITestService的print方法的请求
class BpTestService: public BpInterface
{
public:
//构造函数,首先在参数列表中将IBinder参数传递给BpInterface
BpTestService( const sp& impl )
: BpInterface( 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
#include
#include
#include
#include
#include
#include
#include
#include "ITestService.h"
#include "TestService.h"
using namespace android;
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
//获取servicemanager对象
sp 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ITestService.h"
using namespace android;
class TestServiceDeath:public IBinder::DeathRecipient
{
public:
virtual void binderDied(const wp& who)
{
LOGD("TestService died notification");
}
};
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
ProcessState::self()->startThreadPool();
sp binder = defaultServiceManager()->getService(String16("test.service"));
sp dethNotify = new TestServiceDeath();
binder->linkToDeath( dethNotify );
if ( binder != NULL ) {
//interface_cast(binder) 直接把IBinder类型对象binder转化成了ITestService
sp testServiceProxy = interface_cast( binder );
testServiceProxy->print(String8("hello world"));
}
IPCThreadState::self()->joinThreadPool();
return 0;
}