Android binder 實例

參考: 深入理解Binder

 

下面給出一個demo實例 

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      # 運行測試

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章