android binder機制簡單使用

需求

    最近公司需要在native層寫一個c++服務,用來與上層通訊,由於自己並不是很精通c++,所以決定從簡單的入手,先嚐試寫一個binder服務。


具體實現

    實現一個binder通信實例,需要經過以下步驟:
        1、獲得ServiceManager的對象引用
        2、向ServiceManager註冊新的Service
        3、在Client中通過ServiceManager獲得Service對象引用
        4、在Client中發送請求,由Service返回結果。

具體代碼:

1、編寫myservic.h文件

#include <utils/threads.h>
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/BpBinder.h>
#include <binder/Parcel.h>

namespace android {
    class MyService : public BBinder    
    {
        mutable Mutex mLock;
        int32_t mNextConnId;
        public:
            static int instantiate();
            MyService();
            virtual ~MyService();
            virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
    };
}; //namespace
2、編寫myservice.cpp文件
#include "myservice.h"
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
  
namespace android {
    static struct sigaction oldact;
    static pthread_key_t sigbuskey;

    int MyService::instantiate()    
    {
        LOGE("MyService instantiate");
        // defaultServiceManager ()獲得ServiceManager的對象引用,addService()可向ServiceManager註冊新的服務
        int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService());
        LOGE("MyService r = %d/n", r);
        return r;
    }

    MyService::MyService()
    {
        LOGV("MyService created");
        mNextConnId = 1;
        pthread_key_create(&sigbuskey, NULL);
    }

    MyService::~MyService()
    {
        pthread_key_delete(sigbuskey);
        LOGV("MyService destroyed");
    }    

    // 每個系統服務都繼承自BBinder類,都應重寫BBinder的onTransact虛函數。當用戶發送請求到達Service時,系統框架會調用Service的onTransact函數,該函數分析接收到的數據包,調用相應的接口函數處理請求
    status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        switch(code)
        {
            case 0: {
                pid_t pid = data.readInt32();
                int num   = data.readInt32();
                num = num + 100;
                reply->writeInt32(num);
                return NO_ERROR;
                }
                break;
            default:
                return BBinder::onTransact(code, data, reply, flags);
        }
    }
}; //namespace 
3、編寫Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := myservice.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := libutils libbinder
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libmyservice
include $(BUILD_SHARED_LIBRARY)

mk文件寫完之後進行編譯,編譯完生成libmyservice.so文件。

4、編寫myserver.cpp文件與相應的mk文件

#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 "../libmyservice/myservice.h"

using namespace android;
  
int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();//獲得ServiceManager接口
    LOGI("ServiceManager: %p", sm.get());
    MyService::instantiate();    
    //執行addService()函數,註冊服務  
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    //進入循環,等待客戶端的請求  
    return 0;    
}

mk文件:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
    myserver.cpp  

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
    libutils libbinder libmyservice  

LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := myserver
include $(BUILD_EXECUTABLE)
編譯生成可執行文件myserver。5、編寫myclient.h文件
namespace android
{
    class MyClient {
    public:
        void add100(int n);
        private:
        static const void getMyService();  
        //通過ServiceManager獲取服務接口  
    };
}; //namespace
6、編寫myclient.cpp文件
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "myclient.h"
  
namespace android
{
    sp<IBinder> binder;
    void MyClient::add100(int n)
    {
        getMyService();
        Parcel data, reply;
        int answer;
        data.writeInt32(getpid());
        data.writeInt32(n);
        LOGE("BpMyService::create remote()->transact()/n");
        binder->transact(0, data, &reply);
        answer = reply.readInt32();
        printf("answner=%d/n", answer);
        return;
    }

    const void MyClient::getMyService()
    {
        sp<IServiceManager> sm = defaultServiceManager();
        binder = sm->getService(String16("android.myservice")); 
        LOGE("MyClient::getMyService %p/n",sm.get());
        if (binder == 0) {
            LOGW("MyService not published, waiting...");
            return;
        }
    }
}; //namespace

using namespace android;

int main(int argc, char** argv)
{
    MyClient* p = new MyClient();  
    p->add100(1);
    return 0;
}
7、編寫client端的Android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
    myclient.cpp  

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
    libutils libbinder libmyservice  

LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := myclient

include $(BUILD_EXECUTABLE)
寫完之後編譯生成myclient可執行文件。


一個binder的服務端與客戶端的例子就寫好了,生成的so文件push到system/lib/下面,兩個可執行文件push到system/bin/目錄下。




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