【Android(安卓)Native Code开发系列】六 一个Native Service的完整示例
/*
* blackboy psyc209@163.com
* QQ群:135202158
* 转载请注明作者及出处
*/
关于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
#ifndef ANDROID_ZPSERVICE_H#define ANDROID_ZPSERVICE_H#include <utils/RefBase.h>#include <binder/IInterface.h>#include <binder/Parcel.h>namespace android{class ZPService : public BBinder{private://mutable Mutex m_Lock;//int32_t m_NextConnId;public:static int Instance();ZPService();virtual ~ZPService();virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);};}#endif
ZPService.cpp
#include <binder/IServiceManager.h>#include <binder/IPCThreadState.h>#include "ZPService.h"namespace android{//static struct sigaction oldact;static pthread_key_t sigbuskey;int ZPService::Instance(){LOGE("ZPService Instantiate\n");int ret = defaultServiceManager()->addService(String16("zp.svc"), new ZPService());LOGE("ZPService ret = %d\n", ret);return ret;}ZPService::ZPService(){LOGV("ZPService create\n");//m_NextConnId = 1;pthread_key_create(&sigbuskey,NULL);}ZPService::~ZPService(){pthread_key_delete(sigbuskey);LOGV("ZPService destory\n");}status_t ZPService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){switch(code){case 0: {pid_t pid = data.readInt32();int num = data.readInt32();num += 1000;reply->writeInt32(num);return NO_ERROR;} break;default:return BBinder::onTransact(code, data, reply, flags);}}}
Android.mk
LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:=ZPService.cppLOCAL_SHARED_LIBRARIES:=libutils libbinderLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=libZPServiceLOCAL_PRELINK_MODULE:=falseinclude $(BUILD_SHARED_LIBRARY)
4. 建立svcserver目录,放置server源代码, 它主要用来将我们的service注册到系统.
zpserver.cpp
#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <grp.h>#include <binder/IPCThreadState.h>#include <binder/ProcessState.h>#include <binder/IServiceManager.h>#include <utils/Log.h>#include "../service/ZPService.h"using namespace android;int main(int arg, char** argv){printf("server - ain() begin\n");sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();//LOGI("ServiceManager: %p\n", sm.get());printf("server - erviceManager: %p\n", sm.get());int ret = ZPService::Instance();printf("server - ZPService::Instance return %d\n", ret);ProcessState::self()->startThreadPool();
Android.mk
LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:=zpserver.cppLOCAL_SHARED_LIBRARIES:=libutils libbinder libZPServiceLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=zpserverinclude $(BUILD_EXECUTABLE)
5. 创建svcclient目录, 放置client源代码,它用于调用service提供的服务. 它编译成一个动态库,供其他可执行程序调用, 也可以直接将它和第6步的调用程序直接编译成一个可执行文件
ZPClient.h
#ifndef ANDROID_ZPCLIENT_H#define ANDROID_ZPCLIENT_Hnamespace android{class ZPClient{public:int setN(int n);private:static void getZPService();};}#endif
ZPClient.cpp
#include <binder/IServiceManager.h>#include <binder/IPCThreadState.h>#include "ZPClient.h"namespace android{sp<IBinder> binder;int ZPClient::setN(int n){getZPService();Parcel data, reply;data.writeInt32(getpid());data.writeInt32(n);LOGE("client - binder->transact()\n");binder->transact(0, data, &reply);int r = reply.readInt32();return r;}void ZPClient::getZPService(){sp<IServiceManager> sm = defaultServiceManager();binder = sm->getService(String16("zp.svc"));LOGE("client - etService: %p\n", sm.get());if(binder == 0){LOGW("ZPService not published, waiting...");return;}}}
Android.mk
LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:=ZPClient.cppLOCAL_SHARED_LIBRARIES:=libutils libbinderLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=libZPClientLOCAL_PRELINK_MODULE:=falseinclude $(BUILD_SHARED_LIBRARY)
6. 创建svctest目录, 在里面开发一个测试程序,调用第5步的client库提供的接口,访问我们的service
test.cpp
#include <stdio.h>#include "../svcclient/ZPClient.h"using namespace android;int main(int argc, char** argv){ZPClient client;int ret = client.setN(2012);printf("setN return: %d\n", ret);return 0;}
LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:=test.cppLOCAL_SHARED_LIBRARIES:=libZPClientLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=svctestinclude $(BUILD_EXECUTABLE)
完成以上几步后, 我们的工程的目录结构如下(zp_module的父目录是development):
zp_module/|-- Android.mk|-- service| |-- Android.mk| |-- ZPService.cpp| `-- ZPService.h|-- svcclient| |-- Android.mk| |-- ZPClient.cpp| `-- ZPClient.h|-- svcserver| |-- Android.mk| `-- zpserver.cpp`-- svctest |-- Android.mk `-- test.cpp
7. 编译所有项目
第一种方法, 进入android源码主目录,运行
source build/envsetup.sh 或 . build/envsetup.sh
然后进入development下你的源代码的各个子目录, 根据信赖性先后依次编译各个项目,比如进入development/zp_module/service, 运行 mm
第二种方法, 在zp_module下创建一个Android.mk文件, 输入以下内容:
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即准备好), 将编译好的库和可执行程序送入模拟器
zp@zp-desktop:~$ adb remountremount succeededzp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPService.so /system/lib210 KB/s (10216 bytes in 0.047s)zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPClient.so /system/lib122 KB/s (5516 bytes in 0.044s)zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/zpserver /data124 KB/s (5572 bytes in 0.043s) zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/svctest /data121 KB/s (5568 bytes in 0.044s)
(3) 进入模拟器shell,先后运行zpserver和svctest
zp@zp-desktop:~$ adb shell# /data/zpserverserver - ain() beginserver - erviceManager: 0xaa88server - ZPService::Instance return 0zp@zp-desktop:~$ adb shell# /data/svctestsetN return: 3012#
证明一切正确.
更多相关文章
- Mac OSX 下 手动更新 Android(安卓)Studio
- Android(安卓)指纹识别注意升级问题
- android 建立sdcard 并放文件 在程序中取文件
- Android命令生成编译出build.xml文件
- linux 编译 android-apk 安装到window下的模拟器(步骤)
- Android培训班(10)
- Ubuntu 11.10编译Android(安卓)错误
- Android(安卓)ROM的制作与烧录
- 在MAC下面用 eclipse调试android 6.0 framework