注意:编译这个示例的方式是把这些文件放在packages/apps/里或者externals中,然后运行mm进行编译,编译好的文件在out/target/product/generic/system/bin下面。adb push到Android 模拟器,然后在adb shell中运行,需要打开二个adb shell一个运行nativeserver,另一个运行nativeclient,最好再用DDMS查看logcat,TAG是native_binder。
Android.mk:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nativeclient LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := mathinterface.cpp \ client.cpp LOCAL_SHARED_LIBRARIES := libutils libcutils libbinder LOCAL_C_INCLUDES += frameworks/base/include system/core/include include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := nativeserver LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := mathinterface.cpp \ server.cpp LOCAL_SHARED_LIBRARIES := libutils libcutils libbinder LOCAL_C_INCLUDES += frameworks/base/include system/core/include include $(BUILD_EXECUTABLE)The interface:
/** * Demonstrate how to us Binder in Native C++ codes. * * The interface describes the RPC calls. * * Based on BinderDemo: https://github.com/gburca/BinderDemo/blob/master/binder.cpp */ #ifndef _MATH_INTERFACE_H #define _MATH_INTERFACE_H #define LOG_TAG "native_binder" #include <stdlib.h> #include <binder/IBinder.h> #include <utils/Log.h> #include <utils/TextOutput.h> using namespace android; #define INFO(...) \ do { \ printf(__VA_ARGS__); \ printf("\n"); \ LOGD(__VA_ARGS__); \ } while (0) /** * The interface describing the RPC methods. * * RefBase is the base class for smart pointer. */ class MathInterface : public RefBase { public: enum { PRINT = IBinder::FIRST_CALL_TRANSACTION, ADD }; virtual void print(const char *msg) = 0; virtual int32_t add(int32_t a, int32_t b) = 0; static const String16 DESCRIPTOR; MathInterface(); virtual ~MathInterface(); }; #endif
/** * Demonstrate how to us Binder in Native C++ codes. * * The interface describes the RPC calls. * * Based on BinderDemo: https://github.com/gburca/BinderDemo/blob/master/binder.cpp */ #include "mathinterface.h" const String16 MathInterface::DESCRIPTOR("MathInterface"); MathInterface::MathInterface() { INFO("MathInterface::MathInterface()"); } MathInterface::~MathInterface() { INFO("MathInterface::~MathInterface()"); }Client:
/** * Demonstrate how to us Binder in Native C++ codes. * * The interface describes the RPC calls. * * Based on BinderDemo: https://github.com/gburca/BinderDemo/blob/master/binder.cpp */ #include <stdlib.h> #include <binder/IBinder.h> #include <binder/IServiceManager.h> #include <binder/Parcel.h> #include <utils/TextOutput.h> #include "mathinterface.h" using namespace android; /** * The proxy used for client side. */ class MathBinderProxy : public MathInterface { private: sp<IBinder> remote; public: MathBinderProxy(const sp<IBinder>& impl); void print(const char *msg); int32_t add(int32_t a, int32_t b); }; MathBinderProxy::MathBinderProxy(const sp<IBinder>& impl) { INFO("MathBinderProxy::MathBinderProxy()"); remote = impl; } void MathBinderProxy::print(const char *msg) { Parcel data, reply; data.writeInterfaceToken(MathInterface::DESCRIPTOR); data.writeString16(String16(msg)); aout << "MathBinderProxy::print parcel to be sent:\n"; data.print(aout); endl(aout); remote->transact(MathInterface::PRINT, data, &reply, IBinder::FLAG_ONEWAY); INFO("MathBinderProxy::print() is returned"); } int32_t MathBinderProxy::add(int32_t a, int32_t b) { Parcel data, reply; data.writeInterfaceToken(MathInterface::DESCRIPTOR); data.writeInt32(a); data.writeInt32(b); aout << "MathBinderProxy::add parcel to be sent:\n"; data.print(aout); endl(aout); remote->transact(MathInterface::ADD, data, &reply); INFO("MathBinderProxy::add transact reply"); reply.print(aout); endl(aout); int32_t res; status_t status = reply.readInt32(&res); INFO("MathBinderProxy::add(%i, %i) = %i(status: %i)", a, b, res, status); return res; } static sp<MathInterface> getMathServer(const char *msg) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16(msg)); if (binder == NULL) { INFO("getmath server, cannot find server '%s'", msg); return NULL; } sp<MathInterface> svr = new MathBinderProxy(binder); return svr; } int main(int argc, char **argv) { INFO("we are the client"); const char *native = "MathServer"; const char *java = "JavaServerService"; sp<MathInterface> svc = getMathServer(java); if (svc == NULL) { INFO("failed to find service"); return -1; } svc->print("Hello, welcome to the world of native binder"); int32_t s = svc->add(2013, 3102); INFO("Addition result: %i + %i = %i", 2013, 3102, s); return 0; }Server:
/** * Demonstrate how to us Binder in Native C++ codes. * * The interface describes the RPC calls. * * Based on BinderDemo: https://github.com/gburca/BinderDemo/blob/master/binder.cpp */ #include <stdlib.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include <utils/TextOutput.h> #include "mathinterface.h" using namespace android; /** * The remote binder or the server. */ class MathBinder : public BBinder { protected: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); public: virtual void print(const char *msg); virtual int32_t add(int32_t a, int32_t b); }; status_t MathBinder::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { INFO("MathBinder::onTransact(%i) %i", code, flags); /* * Before executing actual method, check whether the RPC are from expected client. * Client will write interface token, to identify interface to which those methods * belong. */ if (!data.enforceInterface(MathInterface::DESCRIPTOR)) { INFO("failed to check Interface, you might call wrong service, this is for '%s'", String8(MathInterface::DESCRIPTOR).string()); return BAD_TYPE; } data.print(aout); endl(aout); switch(code) { case MathInterface::PRINT: { String16 msg = data.readString16(); print(String8(msg).string()); return NO_ERROR; } case MathInterface::ADD: { int32_t a = data.readInt32(); int32_t b = data.readInt32(); int32_t sum = add(a, b); INFO("MathBinder:onTransact add(%i, %i) = %i", a, b, sum); reply->print(aout); endl(aout); reply->writeInt32(sum); return NO_ERROR; } default: INFO("MathBinder, bad requesting code, no match found"); } return BBinder::onTransact(code, data, reply, flags); } void MathBinder::print(const char *msg) { INFO("MathBinder::print, msg is '%s'", msg); } int32_t MathBinder::add(int32_t a, int32_t b) { return a + b; } int main(int argc, char **argv) { INFO("We're the service"); defaultServiceManager()->addService(String16("MathServer"), new MathBinder()); ProcessState::self()->startThreadPool(); INFO("Math server is running now"); IPCThreadState::self()->joinThreadPool(); INFO("Math server thread joined"); return 0; }