/*
* blackboy [email protected]
* QQ群: 135202158
* 转载请注明作者及出处
*/
关于Android Native Service的简介及一些例子, 还可以参考longfeey的大作: http://blog.csdn.net/longfeey/article/details/5887026
(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组件)
cd ~/android/development
mkdir zp_module
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.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=libZPService LOCAL_PRELINK_MODULE:=false include $(BUILD_SHARED_LIBRARY)
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();
LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:=zpserver.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder libZPService LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=zpserver include $(BUILD_EXECUTABLE)
ZPClient.h
#ifndef ANDROID_ZPCLIENT_H #define ANDROID_ZPCLIENT_H namespace 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.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=libZPClient LOCAL_PRELINK_MODULE:=false include $(BUILD_SHARED_LIBRARY)
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.cpp LOCAL_SHARED_LIBRARIES:=libZPClient LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=svctest include $(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
第一种方法, 进入android源码主目录,运行
source build/envsetup.sh 或 . build/envsetup.sh
然后进入development下你的源代码的各个子目录, 根据信赖性先后依次编译各个项目,比如进入development/zp_module/service, 运行 mm
第二种方法, 在zp_module下创建一个Android.mk文件, 输入以下内容:
include $(call all-subdir-makefiles
(1) 打开emulator
emulator -avd avd4.0.3 -scale 0.6 -partition-size 256
(2) 打开adb, 等avd就绪后(用adb get-state查看状态,为device即准备好), 将编译好的库和可执行程序送入模拟器
zp@zp-desktop:~$ adb remount remount succeeded zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPService.so /system/lib 210 KB/s (10216 bytes in 0.047s) zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/lib/libZPClient.so /system/lib 122 KB/s (5516 bytes in 0.044s) zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/zpserver /data 124 KB/s (5572 bytes in 0.043s) zp@zp-desktop:~$ adb push /home/zp/android/out/target/product/generic/system/bin/svctest /data 121 KB/s (5568 bytes in 0.044s)
(3) 进入模拟器shell,先后运行zpserver和svctest
zp@zp-desktop:~$ adb shell # /data/zpserver server - ain() begin server - erviceManager: 0xaa88 server - ZPService::Instance return 0 zp@zp-desktop:~$ adb shell # /data/svctest setN return: 3012 #
证明一切正确.