一个Native Service的完整示例

来源:互联网 发布:mysql区分大小写查询 编辑:程序博客网 时间:2024/05/19 01:59
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
  1. #ifndef ANDROID_ZPSERVICE_H
  2. #define ANDROID_ZPSERVICE_H

  3. #include <utils/RefBase.h>
  4. #include <binder/IInterface.h>
  5. #include <binder/Parcel.h>

  6. namespace android
  7. {
  8.     class ZPService : public BBinder
  9.     {
  10.     private:
  11.         //mutable Mutex m_Lock;
  12.         //int32_t m_NextConnId;

  13.     public:
  14.         static int Instance();
  15.         ZPService();
  16.         virtual ~ZPService();
  17.         virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
  18.     };
  19. }

  20. #endif
ZPService.cpp

  1. #include <binder/IServiceManager.h>
  2. #include <binder/IPCThreadState.h>
  3. #include "ZPService.h"

  4. namespace android
  5. {
  6.     //static struct sigaction oldact;
  7.     static pthread_key_t sigbuskey;
  8.     
  9.     int ZPService::Instance()
  10.     {
  11.         LOGE("ZPService Instantiate\n");
  12.         int ret = defaultServiceManager()->addService(
  13.                 String16("zp.svc"), new ZPService());
  14.         LOGE("ZPService ret = %d\n", ret);
  15.         return ret;
  16.     }

  17.     ZPService::ZPService()
  18.     {
  19.         LOGV("ZPService create\n");
  20.         //m_NextConnId = 1;
  21.         pthread_key_create(&sigbuskey,NULL);
  22.     }

  23.     ZPService::~ZPService()
  24.     {
  25.         pthread_key_delete(sigbuskey);
  26.         LOGV("ZPService destory\n");
  27.     }

  28.     status_t ZPService::onTransact(uint32_t code, 
  29.                                  const Parcel& data, 
  30.                                  Parcel* reply,
  31.                                  uint32_t flags)
  32.     {
  33.         switch(code)
  34.         {
  35.         case 0: 
  36.             {
  37.                 pid_t pid = data.readInt32();
  38.                 int num = data.readInt32();
  39.                 num += 1000;
  40.                 reply->writeInt32(num);
  41.                 return NO_ERROR;
  42.             } break;
  43.         default:
  44.             return BBinder::onTransact(code, data, reply, flags);
  45.         }
  46.     }
  47. }
Android.mk

  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

  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. using namespace android;


  11. int main(int arg, char** argv)
  12. {
  13.     printf("server - ain() begin\n");
  14.     sp<ProcessState> proc(ProcessState::self());
  15.     sp<IServiceManager> sm = defaultServiceManager();
  16.     //LOGI("ServiceManager: %p\n", sm.get());
  17.     printf("server - erviceManager: %p\n", sm.get());
  18.     int ret = ZPService::Instance();
  19.     printf("server - ZPService::Instance return %d\n", ret);
  20.     ProcessState::self()->startThreadPool();
Android.mk

  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

  1. #ifndef ANDROID_ZPCLIENT_H
  2. #define ANDROID_ZPCLIENT_H

  3. namespace android
  4. {
  5.     class ZPClient
  6.     {
  7.     public:
  8.         int setN(int n);
  9.     private:
  10.         static void getZPService();
  11.     };
  12. }

  13. #endif
ZPClient.cpp

点击(此处)折叠或打开

  1. #include <binder/IServiceManager.h>
  2. #include <binder/IPCThreadState.h>
  3. #include "ZPClient.h"


  4. namespace android
  5. {
  6.     sp<IBinder> binder;
  7.     
  8.     int ZPClient::setN(int n)
  9.     {
  10.         getZPService();
  11.         Parcel data, reply;
  12.         data.writeInt32(getpid());
  13.         data.writeInt32(n);
  14.         
  15.         LOGE("client - binder->transact()\n");
  16.         binder->transact(0, data, &reply);
  17.         int r = reply.readInt32();
  18.         return r;
  19.     }

  20.     void ZPClient::getZPService()
  21.     {
  22.         sp<IServiceManager> sm = defaultServiceManager();
  23.         binder = sm->getService(String16("zp.svc"));
  24.         LOGE("client - etService: %p\n", sm.get());
  25.         if(binder == 0)
  26.         {
  27.             LOGW("ZPService not published, waiting...");
  28.             return;
  29.         }
  30.     }

  31. }
Android.mk

  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

  1. #include <stdio.h>
  2. #include "../svcclient/ZPClient.h"

  3. using namespace android;

  4. int main(int argc, char** argv)
  5. {
  6.     ZPClient client;
  7.     int ret = client.setN(2012);
  8.     printf("setN return: %d\n", ret);
  9.     return 0;
  10. }
Android.mk
 
  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):

点击(此处)折叠或打开

  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文件, 输入以下内容:

  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即准备好), 将编译好的库和可执行程序送入模拟器

  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/(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/(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/(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/(5568 bytes in 0.044s)
(3) 进入模拟器shell,先后运行zpserver和svctest

  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
阅读全文
0 0
原创粉丝点击