C++使用binder实例
Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度上就能理解程序运行的流程。
这是一个用C++写的binder,一个服务器一恶搞客户端,代码如下:
server.cpp
1 #include <binder/IServiceManager.h> 2 #include <binder/IBinder.h> 3 #include <binder/Parcel.h> 4 #include <binder/ProcessState.h> 5 #include <binder/IPCThreadState.h> 6 #include <android/log.h> 7 using namespace android; 8 #ifdef LOG_TAG 9 #undef LOG_TAG 10 #endif 11 #define LOG_TAG "testService" 12 13 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__) 14 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__) 15 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__) 16 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__) 17 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "ProjectName", __VA_ARGS__) 18 19 class MyService : public BBinder 20 { 21 public: 22 MyService() 23 { 24 mydescriptor = String16("media.hello"); 25 n=0; 26 } 27 virtual ~MyService() {} 28 //This function is used when call Parcel::checkInterface(IBinder*) 29 virtual const String16& getInterfaceDescriptor() const 30 { 31 LOGE("this is enter ==========getInterfaceDescriptor"); 32 return mydescriptor; 33 } 34 protected: 35 void show() 36 { 37 LOGE("this is for test show!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 38 LOGE("this is for test show!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 39 LOGE("this is for test show!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 40 LOGE("this is for test show!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 41 LOGE("this is for test show!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 42 } 43 virtual status_t onTransact( uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags = 0) 44 { 45 LOGD("enter MyService onTransact and the code is %d",code); 46 /* 47 if (data.checkInterface(this)) 48 LOGD("checkInterface OK"); 49 else 50 { 51 LOGW("checkInterface failed"); 52 return BBinder::onTransact(code, data, reply, flags); 53 } 54 */ 55 switch (code) 56 { 57 case 1: 58 LOGD("MyService interface 1"); 59 break; 60 case 2: 61 LOGD("MyService interface 2"); 62 cb = data.readStrongBinder(); 63 break; 64 case 3: 65 { 66 LOGD("MyService interface 3, exit"); 67 //No unregister service routine? 68 //It should return to client first and then call exit in another place. 69 exit(0); 70 break; 71 } 72 case 4: 73 {//call cb 74 LOGD("MyService interface 4 before if================"); 75 cb = data.readStrongBinder(); 76 if (cb != NULL) 77 { 78 LOGD("MyService interface 4"); 79 Parcel in, out; 80 in.writeInterfaceToken(String16("android.os.ISetupCallback")); 81 in.writeInt32(n++); //向客户端发送数据 82 83 in.writeCString("This is a string !"); 84 cb->transact(2, in, &out, 0); 85 show(); 86 } 87 break; 88 } 89 default: 90 return BBinder::onTransact(code, data, reply, flags); 91 } 92 return 0; 93 } 94 private: 95 String16 mydescriptor; 96 sp<IBinder> cb; 97 int n; 98 }; 99 int main() 100 { 101 sp<IServiceManager> sm = defaultServiceManager(); //获取ServiceManager服务代理 102 status_t ret; 103 //register MyService to ServiceManager 104 MyService* srv = new MyService(); 105 ret = sm->addService(String16("media.hello"), srv); // 注册服务 106 LOGD("addservice media.hello return %d", ret); 107 //call binder thread pool to start 108 ProcessState::self()->startThreadPool(); 109 IPCThreadState::self()->joinThreadPool(true); //参数默认也是true,进入服务的循环监听状态 110 return 0; 111 }
clinet.cpp
1 #include <binder/IServiceManager.h> 2 #include <binder/IBinder.h> 3 #include <binder/Parcel.h> 4 #include <binder/ProcessState.h> 5 #include <binder/IPCThreadState.h> 6 #include <private/binder/binder_module.h> 7 #include <android/log.h> 8 9 using namespace android; 10 #ifdef LOG_TAG 11 #undef LOG_TAG 12 #endif 13 #define LOG_TAG "testCallback" 14 15 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__) 16 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__) 17 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__) 18 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__) 19 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "ProjectName", __VA_ARGS__) 20 21 class MySetupCallback : public BBinder 22 { 23 public: 24 MySetupCallback() 25 { 26 mydescriptor = String16("android.os.ISetupCallback"); 27 } 28 virtual ~MySetupCallback() {} 29 virtual const String16& getInterfaceDescriptor() const 30 { 31 return mydescriptor; 32 } 33 protected: 34 virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 35 { 36 LOGD("enter MySetupCallback onTransact, code=%u", code); 37 if (data.checkInterface(this)) //检查 mydescriptor 类描述字符串 38 LOGD("checkInterface OK"); 39 else 40 { 41 LOGW("checkInterface failed"); 42 return -1; 43 } 44 switch (code) //code为服务器发送的code,根据code实现不同的函数 45 { 46 case 1: 47 LOGD("From Server code = %u", code); 48 LOGD("From Server code = %u", code); 49 break; 50 case 2: 51 { 52 LOGD("From Server code = %u", code); 53 LOGD("Frome server data = %d", data.readInt32()); //从服务端接收数据 54 LOGD("Frome server string = %s", data.readCString()); 55 56 break; 57 } 58 default: 59 break; 60 } 61 return 0; 62 } 63 private: 64 String16 mydescriptor; 65 }; 66 67 int main() 68 { 69 sp<IServiceManager> sm = defaultServiceManager(); //获取ServiceManager服务代理 70 sp<IBinder> b = sm->getService(String16("media.hello")); //查询服务 71 if (b == NULL) 72 { 73 LOGW("Can't find binder service \"media.hello\""); 74 return -1; 75 } 76 Parcel in1,out1; 77 MySetupCallback *cb = new MySetupCallback(); 78 in1.writeStrongBinder(sp<IBinder>(cb)); 79 int ret = b->transact(4, in1, &out1, 0); //TRANSACTION_registerSetup = 4 80 LOGD("transact(4) return %d", ret); 81 ProcessState::self()->startThreadPool(); 82 IPCThreadState::self()->joinThreadPool(); //参数默认也是true,进入服务的循环监听状态 83 return 0; 84 }
Android.mk
# Copyright 2006 The Android Open Source Project LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \ libcutils \ libbinder \ libutils \ libhardware LOCAL_SRC_FILES:= client.cpp LOCAL_MODULE_TAGS = eng tests LOCAL_MODULE:= testClient include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \ libcutils \ libbinder \ libutils \ libhardware LOCAL_SRC_FILES:=server.cpp LOCAL_MODULE:= testServer LOCAL_MODULE_TAGS = eng tests include $(BUILD_EXECUTABLE)
客户端运行结果如下:
以上代码参考别人写的做了点修改,有错误的地方欢迎指出来,谢谢。