1. 程式人生 > >Android Binder機制的Native應用—雙向通訊

Android Binder機制的Native應用—雙向通訊

mkdir testbinder  //建立testbinder目錄

Android.mk

include $(call all-subdir-makefiles) 

一、介面類

1.正向呼叫—Itestbinder

Itestbinder.h

#ifndef Itestbinder_H  
#define Itestbinder_H 
#include <binder/IInterface.h>
#include "Icallback.h"
namespace android{
  class Itestbinder : public IInterface{
    public:
      DECLARE_META_INTERFACE(testbinder);
      virtual int testinterface(int a) = 0;
      virtual int setcallback(const sp<Icallback>& callback) = 0;
  };
  class Bntestbinder : public BnInterface<Itestbinder>{
  public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
  };
}
#endif
Itestbinder.cpp
#include "Itestbinder.h"
#include <binder/Parcel.h>
#include <binder/IInterface.h>
#include "Icallback.h"
namespace android{
  enum {
    TEST_INTERFACE,
    SET_CALLBACK
  };
//////////////////客戶端
  class Bptestbinder : public BpInterface<Itestbinder>{
    public:
      Bptestbinder(const sp<IBinder>& impl) : BpInterface<Itestbinder>(impl){
      }
      virtual int testinterface(int a){
        LOGD("==========================================================\n");
        LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bptestbinder::testinterface\n");
        Parcel data,reply;
        data.writeInt32(a);
        remote()->transact(TEST_INTERFACE,data,&reply);
        return reply.readInt32();
      }
      virtual int setcallback(const sp<Icallback>& callback){
        LOGD("==========================================================\n");
        LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bptestbinder::setcallback\n");
        Parcel data, reply;
        data.writeStrongBinder(callback->asBinder());
        remote()->transact(SET_CALLBACK, data, &reply);
        return reply.readInt32();
      }
  };

  IMPLEMENT_META_INTERFACE(testbinder, "android.test.Itestbinder");
/////////////////服務端
  status_t Bntestbinder::onTransact(
      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact\n");
    switch (code) {
      case TEST_INTERFACE:{
        //CHECK_INTERFACE(Itestbinder, data, reply);
        LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact>>TEST_INTERFACE\n");
        reply->writeInt32(testinterface((int) data.readInt32()) );
        return NO_ERROR;
      } break;
      case SET_CALLBACK:{
        LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact>>SET_CALLBACK\n");
        sp<Icallback> callback = interface_cast<Icallback>(data.readStrongBinder());
        //int a = connect(Client);
        reply->writeInt32(setcallback(callback));    
        return NO_ERROR;    
      }
      default:{
        LOGD("TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact>>333\n");
        return BBinder::onTransact(code, data, reply, flags);
      }
    }
  }
}
2.反向呼叫—Icallback

Icallback.h

#ifndef Icallback_H  
#define Icallback_H 
#include <binder/IInterface.h>
namespace android{
  class Icallback : public IInterface{
    public:
      DECLARE_META_INTERFACE(callback);
      virtual int notifyCallback(int a) = 0;
  };
  class Bncallback : public BnInterface<Icallback>{
  public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
  };
}
#endif
Icallback.cpp
#include "Itestbinder.h"
#include <binder/Parcel.h>
#include <binder/IInterface.h>
namespace android{
  enum {
    NOTIFY_CALLBACK,
  };
//////////////////客戶端
  class Bpcallback : public BpInterface<Icallback>{
    public:
      Bpcallback(const sp<IBinder>& impl) : BpInterface<Icallback>(impl){
      }
      virtual int notifyCallback(int a){
        LOGD("==========================================================\n");
        LOGD("TK---->>>>>>Icallback.cpp>>>>Bpcallback::notifyCallback\n");
        Parcel data,reply;
        data.writeInt32(a);
        remote()->transact(NOTIFY_CALLBACK,data,&reply);
        return reply.readInt32();
      }
  };

  IMPLEMENT_META_INTERFACE(callback, "android.test.Icallback");
/////////////////服務端
  status_t Bncallback::onTransact(
      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    LOGD("TK---->>>>>>Icallback.cpp>>>>Bncallback::onTransact\n");
    switch (code) {
      case NOTIFY_CALLBACK:{
        //CHECK_INTERFACE(Itestbinder, data, reply);
        LOGD("TK---->>>>>>Icallback.cpp>>>>Bncallback::onTransact>>NOTIFY_CALLBACK\n");
        reply->writeInt32(notifyCallback((int) data.readInt32()) );
        return NO_ERROR;
      } break;
      default:{
        LOGD("TK---->>>>>>Icallback.cpp>>>>Bncallback::onTransact>>222\n");
        return BBinder::onTransact(code, data, reply, flags);
      }
    }
  }
}
二、服務端

mkdir server  //建立server目錄,這個是服務端實現

1.Bntestbinder實現

testbinder.h

#include "../interface/Itestbinder.h"
#include "../interface/Icallback.h"
#include <binder/BinderService.h>
namespace android{
  class testbinder: 
      public BinderService<testbinder>,
      public Bntestbinder{
    friend class BinderService<testbinder>;
    public:
      static const char* getServiceName() { return "test.Itestbinder"; }
      virtual int testinterface(int a);
      virtual int setcallback(const sp<Icallback>& callback);
      virtual     status_t    onTransact(
                                uint32_t code,
                                const Parcel& data,
                                Parcel* reply,
                                uint32_t flags);
    protected:
      sp<Icallback> mcallback;
  };
}
testbinder.cpp
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
//#include <utils/Trace.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/String16.h>
#include <utils/threads.h>
#include <utils/Atomic.h>

//#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <cutils/compiler.h>
#include "testbinder.h"

namespace android{
  int testbinder::testinterface(int a){
    LOGD("TK---->>>>>>testbinder.cpp>>>>testbinder::testinterface\n");
    sp<Icallback> c = mcallback;
    c->notifyCallback(2);
    return a+2;
  }
  int testbinder::setcallback(const sp<Icallback>& callback){
    LOGD("TK---->>>>>>testbinder.cpp>>>>testbinder::setcallback\n");
    mcallback = callback;
    return 1;
  }
  status_t testbinder::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    LOGD("TK---->>>>>>testbinder.cpp>>>>testbinder::onTransact\n");
    return Bntestbinder::onTransact(code, data, reply, flags);
  }
}

2.向ServiceManager註冊testbinder服務

main.cpp
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>

#include "testbinder.h"


using namespace android;

int main(int argc, char** argv)
{
  sp<ProcessState> proc(ProcessState::self());
  sp<IServiceManager> sm = defaultServiceManager();
  LOGI("ServiceManager: %p", sm.get());
  testbinder::instantiate();
  ProcessState::self()->startThreadPool();
  IPCThreadState::self()->joinThreadPool();
  return 0;
}
Android.mk
LOCAL_PATH:= $(call my-dir)
#LOCAL_CFLAGS_ALL :=-I. -I$(LOCAL_PATH)/..

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	main.cpp \
	testbinder.cpp \
	../interface/Itestbinder.cpp \
	../interface/Icallback.cpp

LOCAL_SHARED_LIBRARIES := \
        libui libcutils libutils libbinder libsonivox libicuuc libexpat \
	libdl


LOCAL_MODULE:= server
LOCAL_MODULE_TAGS := optional

三、客戶端

1.通過ServiceManager獲得Itestbinder遠端介面

mkdir client  //建立client目錄,這個是client的實現

client.h

#include "../interface/Itestbinder.h"

namespace android{
  class client{
    public:
      static const sp<Itestbinder>& get_test_binder();
      static sp<Itestbinder> gtestbinder;
  };
}
client.cpp
#include "client.h"
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <stdio.h>
namespace android{
  sp<Itestbinder> client::gtestbinder;
  const sp<Itestbinder>& client::get_test_binder(){
    if (gtestbinder == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16("test.Itestbinder"));
            if (binder != 0)
                break;
            printf("testbinder not published, waiting...");
            usleep(500000); // 0.5 s
        } while (true);
        gtestbinder = interface_cast<Itestbinder>(binder);
    }
    if(gtestbinder==0) printf("no testbinder!?");
    return gtestbinder;
  }
}
2.Bncallback的實現,反向呼叫

callback.h

#include "../interface/Itestbinder.h"
#include "../interface/Icallback.h"
#include <binder/BinderService.h>
namespace android{
  class callback: public Bncallback{
    friend class BinderService<callback>;
    public:
      virtual int notifyCallback(int a);
      virtual     status_t    onTransact(
                                uint32_t code,
                                const Parcel& data,
                                Parcel* reply,
                                uint32_t flags);
  };
}
callback.cpp
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/String16.h>
#include <utils/threads.h>
#include <utils/Atomic.h>

//#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <cutils/compiler.h>
#include "callback.h"

namespace android{
  int callback::notifyCallback(int a){
    LOGD("TK---->>>>>>callback.cpp>>>>callback::notifyCallback\n");
    return 1;
  }
  status_t callback::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    LOGD("TK---->>>>>>callback.cpp>>>>callback::onTransact\n");
    return Bncallback::onTransact(code, data, reply, flags);
  }
}
3.主函式

main.cpp

#include <stdio.h>
#include "client.h"
#include "callback.h"

using namespace android;

int main(int argc, char* argv[]){
  client* myclient = new client();
  if(myclient == NULL) return 0;
  const sp<Itestbinder>& tb = myclient->get_test_binder();
  if(tb == NULL) return 0;
  sp<callback> c = new callback();
  ProcessState::self()->startThreadPool();  //add by tank
  int a = tb->setcallback(c);
  a = tb->testinterface(3);
  LOGD("TK-------->>>result is %d\n",a);
  delete myclient;
  return 0;
}
Android.mk
LOCAL_PATH:= $(call my-dir)
#LOCAL_CFLAGS_ALL :=-I. -I$(LOCAL_PATH)/..

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	client.cpp \
	main.cpp \
	../interface/Itestbinder.cpp \
	callback.cpp \
	../interface/Icallback.cpp \

LOCAL_SHARED_LIBRARIES := \
        libui libcutils libutils libbinder libsonivox libicuuc libexpat \
	libdl


LOCAL_MODULE:= client
LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)
四、執行

./server

./client

結果:

result:

I/        (  563): ServiceManager: 0xd750
D/        (  565): ==========================================================
D/        (  565): TK---->>>>>>Itestbinder.cpp>>>>Bptestbinder::setcallback
D/        (  563): TK---->>>>>>testbinder.cpp>>>>testbinder::onTransact
D/        (  563): TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact
D/        (  563): TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact>>SET_CALLBACK
D/        (  563): TK---->>>>>>testbinder.cpp>>>>testbinder::setcallback
D/        (  565): ==========================================================
D/        (  565): TK---->>>>>>Itestbinder.cpp>>>>Bptestbinder::testinterface
D/        (  563): TK---->>>>>>testbinder.cpp>>>>testbinder::onTransact
D/        (  563): TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact
D/        (  563): TK---->>>>>>Itestbinder.cpp>>>>Bntestbinder::onTransact>>TEST_INTERFACE
D/        (  563): TK---->>>>>>testbinder.cpp>>>>testbinder::testinterface
D/        (  563): ==========================================================
D/        (  563): TK---->>>>>>Icallback.cpp>>>>Bpcallback::notifyCallback
D/        (  565): TK---->>>>>>callback.cpp>>>>callback::onTransact
D/        (  565): TK---->>>>>>Icallback.cpp>>>>Bncallback::onTransact
D/        (  565): TK---->>>>>>Icallback.cpp>>>>Bncallback::onTransact>>NOTIFY_CALLBACK
D/        (  565): TK---->>>>>>callback.cpp>>>>callback::notifyCallback
D/        (  565): TK-------->>>result is 5