【Android Native Code开发系列】六 一个Native Service的完整示例



关于Android Native Service的简介及一些例子, 还可以参考longfeey的大作: http://blog.csdn.net/longfeey/article/details/5887026



1. 准备工作

(1)因为要调用Android源代码的framework/base里的一些类,所以要确保有android相关源代码

(2)需要交叉编译器, 链接器等工具, 这个可以使用anroid源码里提供的工具,也可以使用单独下载的android ndk

(3)可选: 如果在模拟器(AVD)上运行和调试, 还需要有编译好或者单独下载的android sdk及相应的组件等等, 关于各种组件需求,见

http://developer.android.com/sdk/installing.html#components提到的"Recommended Components", 确保满足"Basic"需求 

这里用的环境是android源码+单独下载的SDK(包括sdk toos, sdk platform tools和platform组件)


2. 在android源码主目录/development子目录下建立工程目录, 我们的各个模块的代码都将放在这个目录的子目录下

cd  ~/android/development
mkdir zp_module


3. 建立service目录,里面放要做的native service源码


ZPService.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPSERVICE_H  
  2. #define ANDROID_ZPSERVICE_H  
  3.   
  4. #include <utils/RefBase.h>  
  5. #include <binder/IInterface.h>  
  6. #include <binder/Parcel.h>  
  7.   
  8. namespace android  
  9. {  
  10.     class ZPService : public BBinder  
  11.     {  
  12.     private:  
  13.         //mutable Mutex m_Lock;  
  14.         //int32_t m_NextConnId;  
  15.   
  16.     public:  
  17.         static int Instance();  
  18.         ZPService();  
  19.         virtual ~ZPService();  
  20.         virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);  
  21.     };  
  22. }  
  23.   
  24. #endif  


ZPService.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPService.h"  
  4.   
  5. namespace android  
  6. {  
  7.     //static struct sigaction oldact;  
  8.     static pthread_key_t sigbuskey;  
  9.       
  10.     int ZPService::Instance()  
  11.     {  
  12.         LOGE("ZPService Instantiate\n");  
  13.         int ret = defaultServiceManager()->addService(  
  14.                 String16("zp.svc"), new ZPService());  
  15.         LOGE("ZPService ret = %d\n", ret);  
  16.         return ret;  
  17.     }  
  18.   
  19.     ZPService::ZPService()  
  20.     {  
  21.         LOGV("ZPService create\n");  
  22.         //m_NextConnId = 1;  
  23.         pthread_key_create(&sigbuskey,NULL);  
  24.     }  
  25.   
  26.     ZPService::~ZPService()  
  27.     {  
  28.         pthread_key_delete(sigbuskey);  
  29.         LOGV("ZPService destory\n");  
  30.     }  
  31.   
  32.     status_t ZPService::onTransact(uint32_t code,   
  33.                                    const Parcel& data,   
  34.                                    Parcel* reply,  
  35.                                    uint32_t flags)  
  36.     {  
  37.         switch(code)  
  38.         {  
  39.         case 0:   
  40.             {  
  41.                 pid_t pid = data.readInt32();  
  42.                 int num = data.readInt32();  
  43.                 num += 1000;  
  44.                 reply->writeInt32(num);  
  45.                 return NO_ERROR;  
  46.             } break;  
  47.         default:  
  48.             return BBinder::onTransact(code, data, reply, flags);  
  49.         }  
  50.     }  
  51. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPService.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPService  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


4. 建立svcserver目录,放置server源代码, 它主要用来将我们的service注册到系统. 

zpserver.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <unistd.h>  
  4. #include <grp.h>  
  5. #include <binder/IPCThreadState.h>  
  6. #include <binder/ProcessState.h>  
  7. #include <binder/IServiceManager.h>  
  8. #include <utils/Log.h>  
  9. #include "../service/ZPService.h"  
  10.   
  11. using namespace android;  
  12.   
  13.   
  14. int main(int arg, char** argv)  
  15. {  
  16.     printf("server - ain() begin\n");  
  17.     sp<ProcessState> proc(ProcessState::self());  
  18.     sp<IServiceManager> sm = defaultServiceManager();  
  19.     //LOGI("ServiceManager: %p\n", sm.get());  
  20.     printf("server - erviceManager: %p\n", sm.get());  
  21.     int ret = ZPService::Instance();  
  22.     printf("server - ZPService::Instance return %d\n", ret);  
  23.     ProcessState::self()->startThreadPool();  

Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=zpserver.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder libZPService  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=zpserver  
  7. include $(BUILD_EXECUTABLE)  


5.  创建svcclient目录, 放置client源代码,它用于调用service提供的服务. 它编译成一个动态库,供其他可执行程序调用, 也可以直接将它和第6步的调用程序直接编译成一个可执行文件

ZPClient.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPCLIENT_H  
  2. #define ANDROID_ZPCLIENT_H  
  3.   
  4. namespace android  
  5. {  
  6.     class ZPClient  
  7.     {  
  8.     public:  
  9.         int setN(int n);  
  10.     private:  
  11.         static void getZPService();  
  12.     };  
  13. }  
  14.   
  15. #endif  


ZPClient.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPClient.h"  
  4.   
  5.   
  6. namespace android  
  7. {  
  8.     sp<IBinder> binder;  
  9.       
  10.     int ZPClient::setN(int n)  
  11.     {  
  12.         getZPService();  
  13.         Parcel data, reply;  
  14.         data.writeInt32(getpid());  
  15.         data.writeInt32(n);  
  16.           
  17.         LOGE("client - binder->transact()\n");  
  18.         binder->transact(0, data, &reply);  
  19.         int r = reply.readInt32();  
  20.         return r;  
  21.     }  
  22.   
  23.     void ZPClient::getZPService()  
  24.     {  
  25.         sp<IServiceManager> sm = defaultServiceManager();  
  26.         binder = sm->getService(String16("zp.svc"));  
  27.         LOGE("client - etService: %p\n", sm.get());  
  28.         if(binder == 0)  
  29.         {  
  30.             LOGW("ZPService not published, waiting...");  
  31.             return;  
  32.         }  
  33.     }  
  34.   
  35. }  


Android.mk

[cpp]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPClient.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPClient  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


6. 创建svctest目录, 在里面开发一个测试程序,调用第5步的client库提供的接口,访问我们的service

test.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include "../svcclient/ZPClient.h"  
  3.   
  4. using namespace android;  
  5.   
  6. int main(int argc, char** argv)  
  7. {  
  8.     ZPClient client;  
  9.     int ret = client.setN(2012);  
  10.     printf("setN return: %d\n", ret);  
  11.     return 0;  
  12. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=test.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libZPClient  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=svctest  
  7. include $(BUILD_EXECUTABLE)  


完成以上几步后, 我们的工程的目录结构如下(zp_module的父目录是development):

[plain]  view plain  copy
 print ?
  1. zp_module/  
  2. |-- Android.mk  
  3. |-- service  
  4. |   |-- Android.mk  
  5. |   |-- ZPService.cpp  
  6. |   `-- ZPService.h  
  7. |-- svcclient  
  8. |   |-- Android.mk  
  9. |   |-- ZPClient.cpp  
  10. |   `-- ZPClient.h  
  11. |-- svcserver  
  12. |   |-- Android.mk  
  13. |   `-- zpserver.cpp  
  14. `-- svctest  
  15.     |-- Android.mk  
  16.     `-- test.cpp  



7. 编译所有项目

第一种方法, 进入android源码主目录,运行

source build/envsetup.sh 或 . build/envsetup.sh
然后进入development下你的源代码的各个子目录, 根据信赖性先后依次编译各个项目,比如进入development/zp_module/service, 运行 mm


第二种方法, 在zp_module下创建一个Android.mk文件, 输入以下内容:

[plain]  view plain  copy
 print ?
  1. include $(call all-subdir-makefiles  

然后直接在zp_module目录下运行mm


8. 在模拟器里调试编译好的东西

(1) 打开emulator 

emulator -avd avd4.0.3 -scale 0.6 -partition-size 256

(2) 打开adb, 等avd就绪后(用adb get-state查看状态,为device即准备好), 将编译好的库和可执行程序送入模拟器

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb remount  
  2. remount succeeded  
  3. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPService.so /system/lib  
  4. 210 KB/s (10216 bytes in 0.047s)  
  5. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPClient.so /system/lib  
  6. 122 KB/s (5516 bytes in 0.044s)  
  7. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/zpserver /data  
  8. 124 KB/s (5572 bytes in 0.043s)   
  9. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/svctest /data  
  10. 121 KB/s (5568 bytes in 0.044s)   


(3) 进入模拟器shell,先后运行zpserver和svctest

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb shell  
  2. # /data/zpserver  
  3. server - ain() begin  
  4. server - erviceManager: 0xaa88  
  5. server - ZPService::Instance return 0  
  6. zp@zp-desktop:~$ adb shell  
  7. # /data/svctest  
  8. setN return: 3012  
  9. #  



证明一切正确.



关于Android Native Service的简介及一些例子, 还可以参考longfeey的大作: http://blog.csdn.net/longfeey/article/details/5887026



1. 准备工作

(1)因为要调用Android源代码的framework/base里的一些类,所以要确保有android相关源代码

(2)需要交叉编译器, 链接器等工具, 这个可以使用anroid源码里提供的工具,也可以使用单独下载的android ndk

(3)可选: 如果在模拟器(AVD)上运行和调试, 还需要有编译好或者单独下载的android sdk及相应的组件等等, 关于各种组件需求,见

http://developer.android.com/sdk/installing.html#components提到的"Recommended Components", 确保满足"Basic"需求 

这里用的环境是android源码+单独下载的SDK(包括sdk toos, sdk platform tools和platform组件)


2. 在android源码主目录/development子目录下建立工程目录, 我们的各个模块的代码都将放在这个目录的子目录下

cd  ~/android/development
mkdir zp_module


3. 建立service目录,里面放要做的native service源码


ZPService.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPSERVICE_H  
  2. #define ANDROID_ZPSERVICE_H  
  3.   
  4. #include <utils/RefBase.h>  
  5. #include <binder/IInterface.h>  
  6. #include <binder/Parcel.h>  
  7.   
  8. namespace android  
  9. {  
  10.     class ZPService : public BBinder  
  11.     {  
  12.     private:  
  13.         //mutable Mutex m_Lock;  
  14.         //int32_t m_NextConnId;  
  15.   
  16.     public:  
  17.         static int Instance();  
  18.         ZPService();  
  19.         virtual ~ZPService();  
  20.         virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);  
  21.     };  
  22. }  
  23.   
  24. #endif  


ZPService.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPService.h"  
  4.   
  5. namespace android  
  6. {  
  7.     //static struct sigaction oldact;  
  8.     static pthread_key_t sigbuskey;  
  9.       
  10.     int ZPService::Instance()  
  11.     {  
  12.         LOGE("ZPService Instantiate\n");  
  13.         int ret = defaultServiceManager()->addService(  
  14.                 String16("zp.svc"), new ZPService());  
  15.         LOGE("ZPService ret = %d\n", ret);  
  16.         return ret;  
  17.     }  
  18.   
  19.     ZPService::ZPService()  
  20.     {  
  21.         LOGV("ZPService create\n");  
  22.         //m_NextConnId = 1;  
  23.         pthread_key_create(&sigbuskey,NULL);  
  24.     }  
  25.   
  26.     ZPService::~ZPService()  
  27.     {  
  28.         pthread_key_delete(sigbuskey);  
  29.         LOGV("ZPService destory\n");  
  30.     }  
  31.   
  32.     status_t ZPService::onTransact(uint32_t code,   
  33.                                    const Parcel& data,   
  34.                                    Parcel* reply,  
  35.                                    uint32_t flags)  
  36.     {  
  37.         switch(code)  
  38.         {  
  39.         case 0:   
  40.             {  
  41.                 pid_t pid = data.readInt32();  
  42.                 int num = data.readInt32();  
  43.                 num += 1000;  
  44.                 reply->writeInt32(num);  
  45.                 return NO_ERROR;  
  46.             } break;  
  47.         default:  
  48.             return BBinder::onTransact(code, data, reply, flags);  
  49.         }  
  50.     }  
  51. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPService.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPService  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


4. 建立svcserver目录,放置server源代码, 它主要用来将我们的service注册到系统. 

zpserver.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <unistd.h>  
  4. #include <grp.h>  
  5. #include <binder/IPCThreadState.h>  
  6. #include <binder/ProcessState.h>  
  7. #include <binder/IServiceManager.h>  
  8. #include <utils/Log.h>  
  9. #include "../service/ZPService.h"  
  10.   
  11. using namespace android;  
  12.   
  13.   
  14. int main(int arg, char** argv)  
  15. {  
  16.     printf("server - ain() begin\n");  
  17.     sp<ProcessState> proc(ProcessState::self());  
  18.     sp<IServiceManager> sm = defaultServiceManager();  
  19.     //LOGI("ServiceManager: %p\n", sm.get());  
  20.     printf("server - erviceManager: %p\n", sm.get());  
  21.     int ret = ZPService::Instance();  
  22.     printf("server - ZPService::Instance return %d\n", ret);  
  23.     ProcessState::self()->startThreadPool();  

Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=zpserver.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder libZPService  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=zpserver  
  7. include $(BUILD_EXECUTABLE)  


5.  创建svcclient目录, 放置client源代码,它用于调用service提供的服务. 它编译成一个动态库,供其他可执行程序调用, 也可以直接将它和第6步的调用程序直接编译成一个可执行文件

ZPClient.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPCLIENT_H  
  2. #define ANDROID_ZPCLIENT_H  
  3.   
  4. namespace android  
  5. {  
  6.     class ZPClient  
  7.     {  
  8.     public:  
  9.         int setN(int n);  
  10.     private:  
  11.         static void getZPService();  
  12.     };  
  13. }  
  14.   
  15. #endif  


ZPClient.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPClient.h"  
  4.   
  5.   
  6. namespace android  
  7. {  
  8.     sp<IBinder> binder;  
  9.       
  10.     int ZPClient::setN(int n)  
  11.     {  
  12.         getZPService();  
  13.         Parcel data, reply;  
  14.         data.writeInt32(getpid());  
  15.         data.writeInt32(n);  
  16.           
  17.         LOGE("client - binder->transact()\n");  
  18.         binder->transact(0, data, &reply);  
  19.         int r = reply.readInt32();  
  20.         return r;  
  21.     }  
  22.   
  23.     void ZPClient::getZPService()  
  24.     {  
  25.         sp<IServiceManager> sm = defaultServiceManager();  
  26.         binder = sm->getService(String16("zp.svc"));  
  27.         LOGE("client - etService: %p\n", sm.get());  
  28.         if(binder == 0)  
  29.         {  
  30.             LOGW("ZPService not published, waiting...");  
  31.             return;  
  32.         }  
  33.     }  
  34.   
  35. }  


Android.mk

[cpp]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPClient.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPClient  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


6. 创建svctest目录, 在里面开发一个测试程序,调用第5步的client库提供的接口,访问我们的service

test.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include "../svcclient/ZPClient.h"  
  3.   
  4. using namespace android;  
  5.   
  6. int main(int argc, char** argv)  
  7. {  
  8.     ZPClient client;  
  9.     int ret = client.setN(2012);  
  10.     printf("setN return: %d\n", ret);  
  11.     return 0;  
  12. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=test.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libZPClient  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=svctest  
  7. include $(BUILD_EXECUTABLE)  


完成以上几步后, 我们的工程的目录结构如下(zp_module的父目录是development):

[plain]  view plain  copy
 print ?
  1. zp_module/  
  2. |-- Android.mk  
  3. |-- service  
  4. |   |-- Android.mk  
  5. |   |-- ZPService.cpp  
  6. |   `-- ZPService.h  
  7. |-- svcclient  
  8. |   |-- Android.mk  
  9. |   |-- ZPClient.cpp  
  10. |   `-- ZPClient.h  
  11. |-- svcserver  
  12. |   |-- Android.mk  
  13. |   `-- zpserver.cpp  
  14. `-- svctest  
  15.     |-- Android.mk  
  16.     `-- test.cpp  



7. 编译所有项目

第一种方法, 进入android源码主目录,运行

source build/envsetup.sh 或 . build/envsetup.sh
然后进入development下你的源代码的各个子目录, 根据信赖性先后依次编译各个项目,比如进入development/zp_module/service, 运行 mm


第二种方法, 在zp_module下创建一个Android.mk文件, 输入以下内容:

[plain]  view plain  copy
 print ?
  1. include $(call all-subdir-makefiles  

然后直接在zp_module目录下运行mm


8. 在模拟器里调试编译好的东西

(1) 打开emulator 

emulator -avd avd4.0.3 -scale 0.6 -partition-size 256

(2) 打开adb, 等avd就绪后(用adb get-state查看状态,为device即准备好), 将编译好的库和可执行程序送入模拟器

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb remount  
  2. remount succeeded  
  3. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPService.so /system/lib  
  4. 210 KB/s (10216 bytes in 0.047s)  
  5. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPClient.so /system/lib  
  6. 122 KB/s (5516 bytes in 0.044s)  
  7. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/zpserver /data  
  8. 124 KB/s (5572 bytes in 0.043s)   
  9. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/svctest /data  
  10. 121 KB/s (5568 bytes in 0.044s)   


(3) 进入模拟器shell,先后运行zpserver和svctest

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb shell  
  2. # /data/zpserver  
  3. server - ain() begin  
  4. server - erviceManager: 0xaa88  
  5. server - ZPService::Instance return 0  
  6. zp@zp-desktop:~$ adb shell  
  7. # /data/svctest  
  8. setN return: 3012  
  9. #  



证明一切正确.


转自http://blog.csdn.net/blackboyofsnp/article/details/7243070

关于Android Native Service的简介及一些例子, 还可以参考longfeey的大作: http://blog.csdn.net/longfeey/article/details/5887026



1. 准备工作

(1)因为要调用Android源代码的framework/base里的一些类,所以要确保有android相关源代码

(2)需要交叉编译器, 链接器等工具, 这个可以使用anroid源码里提供的工具,也可以使用单独下载的android ndk

(3)可选: 如果在模拟器(AVD)上运行和调试, 还需要有编译好或者单独下载的android sdk及相应的组件等等, 关于各种组件需求,见

http://developer.android.com/sdk/installing.html#components提到的"Recommended Components", 确保满足"Basic"需求 

这里用的环境是android源码+单独下载的SDK(包括sdk toos, sdk platform tools和platform组件)


2. 在android源码主目录/development子目录下建立工程目录, 我们的各个模块的代码都将放在这个目录的子目录下

cd  ~/android/development
mkdir zp_module


3. 建立service目录,里面放要做的native service源码


ZPService.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPSERVICE_H  
  2. #define ANDROID_ZPSERVICE_H  
  3.   
  4. #include <utils/RefBase.h>  
  5. #include <binder/IInterface.h>  
  6. #include <binder/Parcel.h>  
  7.   
  8. namespace android  
  9. {  
  10.     class ZPService : public BBinder  
  11.     {  
  12.     private:  
  13.         //mutable Mutex m_Lock;  
  14.         //int32_t m_NextConnId;  
  15.   
  16.     public:  
  17.         static int Instance();  
  18.         ZPService();  
  19.         virtual ~ZPService();  
  20.         virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);  
  21.     };  
  22. }  
  23.   
  24. #endif  


ZPService.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPService.h"  
  4.   
  5. namespace android  
  6. {  
  7.     //static struct sigaction oldact;  
  8.     static pthread_key_t sigbuskey;  
  9.       
  10.     int ZPService::Instance()  
  11.     {  
  12.         LOGE("ZPService Instantiate\n");  
  13.         int ret = defaultServiceManager()->addService(  
  14.                 String16("zp.svc"), new ZPService());  
  15.         LOGE("ZPService ret = %d\n", ret);  
  16.         return ret;  
  17.     }  
  18.   
  19.     ZPService::ZPService()  
  20.     {  
  21.         LOGV("ZPService create\n");  
  22.         //m_NextConnId = 1;  
  23.         pthread_key_create(&sigbuskey,NULL);  
  24.     }  
  25.   
  26.     ZPService::~ZPService()  
  27.     {  
  28.         pthread_key_delete(sigbuskey);  
  29.         LOGV("ZPService destory\n");  
  30.     }  
  31.   
  32.     status_t ZPService::onTransact(uint32_t code,   
  33.                                    const Parcel& data,   
  34.                                    Parcel* reply,  
  35.                                    uint32_t flags)  
  36.     {  
  37.         switch(code)  
  38.         {  
  39.         case 0:   
  40.             {  
  41.                 pid_t pid = data.readInt32();  
  42.                 int num = data.readInt32();  
  43.                 num += 1000;  
  44.                 reply->writeInt32(num);  
  45.                 return NO_ERROR;  
  46.             } break;  
  47.         default:  
  48.             return BBinder::onTransact(code, data, reply, flags);  
  49.         }  
  50.     }  
  51. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPService.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPService  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


4. 建立svcserver目录,放置server源代码, 它主要用来将我们的service注册到系统. 

zpserver.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <unistd.h>  
  4. #include <grp.h>  
  5. #include <binder/IPCThreadState.h>  
  6. #include <binder/ProcessState.h>  
  7. #include <binder/IServiceManager.h>  
  8. #include <utils/Log.h>  
  9. #include "../service/ZPService.h"  
  10.   
  11. using namespace android;  
  12.   
  13.   
  14. int main(int arg, char** argv)  
  15. {  
  16.     printf("server - ain() begin\n");  
  17.     sp<ProcessState> proc(ProcessState::self());  
  18.     sp<IServiceManager> sm = defaultServiceManager();  
  19.     //LOGI("ServiceManager: %p\n", sm.get());  
  20.     printf("server - erviceManager: %p\n", sm.get());  
  21.     int ret = ZPService::Instance();  
  22.     printf("server - ZPService::Instance return %d\n", ret);  
  23.     ProcessState::self()->startThreadPool();  

Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=zpserver.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder libZPService  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=zpserver  
  7. include $(BUILD_EXECUTABLE)  


5.  创建svcclient目录, 放置client源代码,它用于调用service提供的服务. 它编译成一个动态库,供其他可执行程序调用, 也可以直接将它和第6步的调用程序直接编译成一个可执行文件

ZPClient.h

[cpp]  view plain  copy
 print ?
  1. #ifndef ANDROID_ZPCLIENT_H  
  2. #define ANDROID_ZPCLIENT_H  
  3.   
  4. namespace android  
  5. {  
  6.     class ZPClient  
  7.     {  
  8.     public:  
  9.         int setN(int n);  
  10.     private:  
  11.         static void getZPService();  
  12.     };  
  13. }  
  14.   
  15. #endif  


ZPClient.cpp

[cpp]  view plain  copy
 print ?
  1. #include <binder/IServiceManager.h>  
  2. #include <binder/IPCThreadState.h>  
  3. #include "ZPClient.h"  
  4.   
  5.   
  6. namespace android  
  7. {  
  8.     sp<IBinder> binder;  
  9.       
  10.     int ZPClient::setN(int n)  
  11.     {  
  12.         getZPService();  
  13.         Parcel data, reply;  
  14.         data.writeInt32(getpid());  
  15.         data.writeInt32(n);  
  16.           
  17.         LOGE("client - binder->transact()\n");  
  18.         binder->transact(0, data, &reply);  
  19.         int r = reply.readInt32();  
  20.         return r;  
  21.     }  
  22.   
  23.     void ZPClient::getZPService()  
  24.     {  
  25.         sp<IServiceManager> sm = defaultServiceManager();  
  26.         binder = sm->getService(String16("zp.svc"));  
  27.         LOGE("client - etService: %p\n", sm.get());  
  28.         if(binder == 0)  
  29.         {  
  30.             LOGW("ZPService not published, waiting...");  
  31.             return;  
  32.         }  
  33.     }  
  34.   
  35. }  


Android.mk

[cpp]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=ZPClient.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libutils libbinder  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=libZPClient  
  7. LOCAL_PRELINK_MODULE:=false  
  8. include $(BUILD_SHARED_LIBRARY)  


6. 创建svctest目录, 在里面开发一个测试程序,调用第5步的client库提供的接口,访问我们的service

test.cpp

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include "../svcclient/ZPClient.h"  
  3.   
  4. using namespace android;  
  5.   
  6. int main(int argc, char** argv)  
  7. {  
  8.     ZPClient client;  
  9.     int ret = client.setN(2012);  
  10.     printf("setN return: %d\n", ret);  
  11.     return 0;  
  12. }  


Android.mk

[plain]  view plain  copy
 print ?
  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:=test.cpp  
  4. LOCAL_SHARED_LIBRARIES:=libZPClient  
  5. LOCAL_MODULE_TAGS:=optional  
  6. LOCAL_MODULE:=svctest  
  7. include $(BUILD_EXECUTABLE)  


完成以上几步后, 我们的工程的目录结构如下(zp_module的父目录是development):

[plain]  view plain  copy
 print ?
  1. zp_module/  
  2. |-- Android.mk  
  3. |-- service  
  4. |   |-- Android.mk  
  5. |   |-- ZPService.cpp  
  6. |   `-- ZPService.h  
  7. |-- svcclient  
  8. |   |-- Android.mk  
  9. |   |-- ZPClient.cpp  
  10. |   `-- ZPClient.h  
  11. |-- svcserver  
  12. |   |-- Android.mk  
  13. |   `-- zpserver.cpp  
  14. `-- svctest  
  15.     |-- Android.mk  
  16.     `-- test.cpp  



7. 编译所有项目

第一种方法, 进入android源码主目录,运行

source build/envsetup.sh 或 . build/envsetup.sh
然后进入development下你的源代码的各个子目录, 根据信赖性先后依次编译各个项目,比如进入development/zp_module/service, 运行 mm


第二种方法, 在zp_module下创建一个Android.mk文件, 输入以下内容:

[plain]  view plain  copy
 print ?
  1. include $(call all-subdir-makefiles  

然后直接在zp_module目录下运行mm


8. 在模拟器里调试编译好的东西

(1) 打开emulator 

emulator -avd avd4.0.3 -scale 0.6 -partition-size 256

(2) 打开adb, 等avd就绪后(用adb get-state查看状态,为device即准备好), 将编译好的库和可执行程序送入模拟器

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb remount  
  2. remount succeeded  
  3. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPService.so /system/lib  
  4. 210 KB/s (10216 bytes in 0.047s)  
  5. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPClient.so /system/lib  
  6. 122 KB/s (5516 bytes in 0.044s)  
  7. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/zpserver /data  
  8. 124 KB/s (5572 bytes in 0.043s)   
  9. zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/svctest /data  
  10. 121 KB/s (5568 bytes in 0.044s)   


(3) 进入模拟器shell,先后运行zpserver和svctest

[plain]  view plain  copy
 print ?
  1. zp@zp-desktop:~$ adb shell  
  2. # /data/zpserver  
  3. server - ain() begin  
  4. server - erviceManager: 0xaa88  
  5. server - ZPService::Instance return 0  
  6. zp@zp-desktop:~$ adb shell  
  7. # /data/svctest  
  8. setN return: 3012  
  9. #  



证明一切正确.

你可能感兴趣的:(【Android Native Code开发系列】六 一个Native Service的完整示例)