參考: 深入理解Binder
下面給出一個demo實例
打印信息頭文件
cur_log.h
#ifndef CUR_LOG_H
#define CUR_LOG_H
#include <android/log.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#undef LOG_TAG
#define LOG_TAG "binder_test"
#define cur_logi(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) /* 普通打印信息 */
#define cur_loge(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) /* 錯誤打印信息 */
// #define cur_logi(fmt, args...) printf("I %s " fmt "\n", LOG_TAG, ##args)
// #define cur_loge(fmt, args...) printf("E %s " fmt "\n", LOG_TAG, ##args)
#define cur_enter() cur_logi("enter %s", __func__)
#define cur_exit() cur_logi("exit %s", __func__)
#ifdef __cplusplus
}
#endif
/* CUR_LOG_H */
#endif
客戶端 服務端 業務接口聲明
IMyService.h
#ifndef IMYSERVICE_H
#define IMYSERVICE_H
#include "cur_log.h"
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/String16.h>
#define MY_SERVICE "coder.Myservice"
using namespace android;
namespace android
{
// 聲明業務接口, Bp Bn 繼承 業務接口
class IMyService : public IInterface
{
public:
// 定義命令字段
enum
{
// SEND_INT = 0 , 可自定義
SEND_INT = IBinder::FIRST_CALL_TRANSACTION,
GET_STRING,
GET_INT,
SAY_HELLO,
};
// 使用宏,聲明 MyService 業務接口,將業務和通信牢牢地鉤在了一起
DECLARE_META_INTERFACE(MyService);
// 聲明方法
virtual void sendInt(int32_t val) = 0;
virtual String8 getString() = 0;
virtual int32_t getInt() = 0;
virtual void sayHello() = 0;
};
// 聲明客戶端 BpMyService
class BpMyService : public BpInterface<IMyService>
{
public:
BpMyService(const sp<IBinder>& impl);
~BpMyService();
virtual void sendInt(int32_t val);
virtual String8 getString();
virtual int32_t getInt();
virtual void sayHello();
};
// 聲明服務端 BnMyService
class BnMyService : public BnInterface<IMyService>
{
public:
// BnXXService實現了onTransact函數,它將根據消息碼調用對應的業務邏輯函數
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
BnMyService();
~BnMyService();
virtual void sendInt(int32_t val);
virtual String8 getString();
virtual int32_t getInt();
virtual void sayHello();
private:
int32_t option;
};
}
#endif
客戶端 服務端 實現
IMyService.cpp
#include "IMyService.h"
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
namespace android
{
// 實現 IMPLEMENT_META_INTERFACE 宏模板定義 MyService 業務接口, 將業務和通信牢牢地鉤在了一起
IMPLEMENT_META_INTERFACE(MyService, MY_SERVICE);
/***************************************************************************************************
* 客戶端
*/
BpMyService::BpMyService(const sp<IBinder>& impl) : BpInterface<IMyService>(impl)
{
}
BpMyService::~BpMyService() {};
void BpMyService::sendInt(int32_t val)
{
Parcel data, reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
data.writeInt32(val);
remote()->transact(SEND_INT, data, &reply);
}
String8 BpMyService::getString()
{
Parcel data, reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
remote()->transact(GET_STRING, data, &reply);
String8 res = reply.readString8();
return res;
}
int32_t BpMyService::getInt()
{
Parcel data, reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
remote()->transact(GET_INT, data, &reply);
int32_t val = reply.readInt32();
return val;
}
void BpMyService::sayHello()
{
Parcel data, reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
remote()->transact(SAY_HELLO, data, &reply);
int32_t val = reply.readInt32();
printf("say hello %d \n", val);
}
/***************************************************************************************************
* 服務端
*/
BnMyService::BnMyService()
{
option = 0;
}
BnMyService::~BnMyService()
{}
/* 接收遠程消息,處理 onTransact 方法 */
status_t BnMyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case SEND_INT:
{
CHECK_INTERFACE(IMyService, data, reply);
int32_t val = data.readInt32(); // 調用服務類的函數
sendInt(val);
return NO_ERROR;
}
break;
case GET_STRING:
{
CHECK_INTERFACE(IMyService, data, reply);
String8 res = getString(); // 調用服務類的函數
reply->writeString8(res);
return NO_ERROR;
}
break;
case GET_INT:
{
CHECK_INTERFACE(IMyService, data, reply);
int32_t val = getInt(); // 調用服務類的函數
reply->writeInt32(val);
return NO_ERROR;
}
break;
case SAY_HELLO:
{
CHECK_INTERFACE(IMyService, data, reply);
sayHello();
reply->writeInt32(2019);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
void BnMyService::sendInt(int32_t val)
{
option = val;
}
int32_t BnMyService::getInt()
{
return option;
}
String8 BnMyService::getString()
{
String8 str;
if(option <= 0)
{
str = String8("val <= 0");
}
else
{
str = String8("val > 0 ");
}
return str;
}
void BnMyService::sayHello()
{
printf("Hello, %s\n", __func__);
}
}
註冊 service 到系統
MyService.cpp
#include "IMyService.h"
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
int main(int argc __unused, char *argv[] __unused)
{
sp < IServiceManager > sm = defaultServiceManager(); //獲取service manager引用
sm->addService(String16(MY_SERVICE), new BnMyService()); // 註冊 MySerivce 服務到系統中
// 開啓線程池,接收處理Client發送的進程間通信請求
ProcessState::self()->startThreadPool(); //啓動線程池
IPCThreadState::self()->joinThreadPool(); //把主線程加入線程池
return 0;
}
客戶端測試
MyService.cpp
#include "IMyService.h"
#include <binder/IServiceManager.h>
int main()
{
sp < IServiceManager > sm = defaultServiceManager(); //獲取service manager引用
sp < IBinder > binder = sm->getService(String16(MY_SERVICE));//獲取名爲 "coder.Myservice" 的binder接口
if(binder == NULL)
{
cur_loge("error, binder = NULL %s", __func__);
return -1;
}
// 獲取 client <--> service
sp<IMyService> service = IMyService::asInterface(binder);
if(service == NULL)
{
cur_loge("error, service = NULL %s", __func__);
}
for(int32_t i = 0; i < 10; i++)
{
service->sendInt(-i);
String8 str1 = service->getString();
cur_logi("val = %d, str1 : %s", service->getInt(), str1.string());
service->sendInt(i);
String8 str2 = service->getString();
cur_logi("val = %d, str2 : %s", service->getInt(), str2.string());
}
service->sayHello();
return 0;
}
Android.mk
LOCAL_PATH := $(call my-dir)
####################
# MyService
####################
include $(CLEAR_VARS)
#LOCAL_MODULE_TAGSS := optional
#LOCAL_MODULE_CLASS := minrray
LOCAL_SRC_FILES := IMyService.cpp \
MyServer.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
$(TOP)/system/core/include/
LOCAL_SHARED_LIBRARIES := libc libutils libcutils liblog libbinder
LOCAL_MODULE := MyService
include $(BUILD_EXECUTABLE)
####################
# Myclient
####################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := IMyService.cpp \
MyClient.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
$(TOP)/system/core/include/
LOCAL_SHARED_LIBRARIES := libc libutils libcutils liblog libbinder
LOCAL_MODULE := MyClient
include $(BUILD_EXECUTABLE)
測試:
MyService & # 運行服務
MyClient # 運行測試