這個月初開始入職實習了,經過這幾天的熟悉,大概瞭解了將來負責的方向了,然後就是開始學習。主要學習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;
}