Android创建Native Binder Service

天是2015.01.09,这一段时间是我工作中特别郁闷的一段日子,公司不景气同时也接近年过了,重新找一份工作也不是特别好的时候。这是一段非常时期,对于程序员来说,那就只能是代码中需求安慰了。这一段时间主要精力都放在看Android源码相关的东西上面了,正好看到网上关于Android创建native binder service相关的只是比较少,在这里我以一个实例来讲解关于怎么在Android下创建Native Binder Service。

首先在编译Binder相关的程序需要链接到Binder动态链接库,应用开发环境下使用ndk编程是不能链接binder动态链接库的,故此需要在源码开发环境下进行,本实例是放在Android源码目录的vender目录下面,然后创建一个NativeBinder文件夹,该文件夹的目录结构如下:

Android.mk 这个不用多说
Test.h 里面定义了本地方法的相关接口和本地接口代理BBxxxx
ITestService.cpp 里面定义了Bpxxxx和Bnxxxx::onTransact
TestService.cpp 这个就是Natavite Binder的实现
TestClient.cpp 这个就是通过Binder对Nataive Binder Service的使用了


1)Android.mk的具体实现,代码如下:

LOCAL_PATH := $(call my-dir)#生成binder service的服务端include $(CLEAR_VARS)LOCAL_SHARED_LIBRARIES := \libcutils \libutils \libbinderLOCAL_MODULE := TestServerLOCAL_SRC_FILES := \TestService.cpp \ITestService.cppLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)include $(CLEAR_VARS)LOCAL_SHARED_LIBRARIES := \libcutils \libutils \libbinderLOCAL_MODULE := TestClientLOCAL_SRC_FILES := \ITestService.cpp \TestClient.cppLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)

关于Android.mk的相关语法问题,我在这里就不多做细说了,如果还不太了解的可以上百度或者谷歌去需求帮助。
2)Android Native Binder Service接口的定义,Test.h具体就是做的这个工作,下面给出代码
#ifndef TEST_H_H#define TEST_H_H#include <stdio.h>#include <binder/IInterface.h>#include <binder/Parcel.h>#include <binder/IBinder.h>#include <binder/Binder.h>#include <binder/ProcessState.h>#include <binder/IPCThreadState.h>#include <binder/IServiceManager.h>using namespace android;namespace android{ class ITestService : public IInterface    {    <span style="white-space:pre"></span>public: <span style="white-space:pre"></span>/*使用该宏,相当于添加了一些代码,后面会有详细分析*/        DECLARE_META_INTERFACE(TestService); // declare macro        virtual void test()=0;    };    enum    {        TEST = IBinder::FIRST_CALL_TRANSACTION,    }; class BnTestService: public BnInterface<ITestService> {<span style="white-space:pre"></span>public:<span style="white-space:pre"></span>virtual status_t<span style="white-space:pre"></span>onTransact(uint32_t code, const Parcel& data, Parcel* reply,uint32_t flags = 0);  virtual void test()  {   printf("Now get test\n");  } };}#endif
(1)使用DECLARE_META_INTERFACE(TestService);相当于添加了下述代码:
     static const android::String16 descriptor;     static android::sp<ITestService> asInterface(     const android::sp<android::IBinder>& obj);     virtual const android::String16& getInterfaceDescriptor() const;     ITestService ();     virtual ~ITestService();
(2)为ITestService接口的所有方法声明枚举,一个枚举值对应ITestService接口的一个方法(Test.h)
enum
{TEST = IBinder::FIRST_CALL_TRANSACTION,};
TEST相当于ITestService接口里的test方法,后续会为该枚举值调用test方法(Test.h) 在这里我想多说两句,如果大家手里有源码的话,可以参照Android多媒体框架的相关源码来学习这里,我这里为什么这样写也不是我自己独创,我也是参照Android源码来进行的。网上说为什么将BnTestService定义在头文件中,而不将BPTestService定义在头文件中,网上所说的是BPTestService对用户是透明的,这个我也没有弄清楚为什是透明的就不定义在这个头文件中呢,这个不在我们这里的讨论范畴之内,就不花多余的时间讨论了。

3)ITestService.cpp,该文件主要创建了BpTestService和实现了BnTestService::onTransact,不多说直接上代码:
#include "Test.h"namespace android{ class BpTestService:public BpInterface<ITestService> {  public:  BpTestService(const sp<IBinder>& impl) :  BpInterface<ITestService>(impl)  {  }  void test()  {    printf("in the get Test\n");             Parcel data, reply;             data.writeInterfaceToken(ITestService::getInterfaceDescriptor());             remote()->transact(TEST, data, &reply);             printf("send Print %d\n", reply.readInt32());  } };    IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService"); status_t BnTestService::onTransact(uint_t code, const Parcel& data,  Parcel* reply, uint32_t flags) {  switch (code) {  case TEST: {   printf("got the client msg\n");   CHECK_INTERFACE(ITest, data, reply);   test();   reply->writeInt32(100);   return NO_ERROR;  }   break;  default:   break;  }  return NO_ERROR; }}

这里我想重点说明的是,该处的IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");和DECLARE_META_INTERFACE(TestService); // declare macro是相互对应的,这个需要大家关注下。写到这里,Android下创建的Native Binder Service的工作已经进行了一大半了,接下来的只需要进行具体操作使用就OK了。
4)实现ITestService接口的方法(ITestService.cpp)
IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService"); 使用IMPLEMENT_META_INTERFACE(TestService, “android.TestServer.ITestService”);相当于添加了下述代码:
/*初始化用宏DECLARE_META_INTERFACE声明的静态字段descriptor*/const android::String16 ITestService::descriptor("android.TestServer.ITestService");/*实现用宏DECLARE_META_INTERFACE声明的方法getInterfaceDescriptor */const android::String16&                     ITestService::getInterfaceDescriptor() const {return ITestService::descriptor;         }                                 /*实现用宏DECLARE_META_INTERFACE声明的方法asInterface */android::sp<ITestService> ITestService::asInterface( const android::sp<android::IBinder>& obj)   {                           android::sp<ITestService> intr;          if (obj != NULL) {     /*在binder实体类BnInterface里会执行queryLocalInterface*/           intr = static_cast<ITestService*>(      obj->queryLocalInterface(         ITestService::descriptor).get()); /*在binder引用类BpInterface里会创建BpInterface的子类对象*/      if (intr == NULL) {              intr = new BpTestService(obj);      }                       }                         return intr;                   }                           /*实现用宏DECLARE_META_INTERFACE声明的构造器和析构器 */ITestService::ITestService() { }          ITestService::~ITestService() { };

5)实现Client端(TestClient.cpp)
    int main()    {sp < IServiceManager > sm = defaultServiceManager();sp < IBinder > binder = sm->getService(String16("service.testservice"));sp<ITestService> cs = interface_cast < ITestService > (binder);cs->test();return 0;    }
Service的Client通过Service Manager拿到的ITestService接口对象其实就是一个binder引用,也就是说其实是一个BpTestService对象,它也会实现ITestService接口的test方法,但是它并没有实现test的功能,而是跨进程调用Binder实体对象BnInterface的test方法。因为 涉及到跨进程调用,所以并没有直接调用,而是通过binder驱动转交给服务进程一些参数,然后就阻塞住。服务进程收到这些参数后,知道client端调用test方法,此时服务端调用test方法,执行完成后把执行结果通过binder驱动再返回给client所在进程,此时client的test方法收到结果后 再返回。 我们再实际的开发过程中并没有直接和binder驱动交互,而是通过Android为binder专门设计的一些核心库和框架来交互,这样就简化了代码编写复杂度。像BpInterface便是核心库和框架提供的一个类,我们在实现时,只需要调用BpInterface的构造器,并实现ITestService接口的test方 法即可,实现test方法时,通过remote()调用transact方法就能把数据提交至service端,servcie的返回结果会放在reply里。interface_cast(binder)实际上调用的方法是用宏DECLARE_META_INTERFACE声明的方法ITestService::asInterface,这里用了内联函数模版。 ProcessState和IPCThreadState是真正直接和binder驱动交互的类,核心库和框架层都是通过和这两个类交互才能和驱动间接交互。它们通过ioctl和binder驱动交互,ProcessState主要负责管理所有的binder引用,IPCThreadState则和binder传输数据。以后如果有时间再详细介绍这两个类。
6)实现Service端(ServiceTest.cpp)
#include "Test.h" namespace android { class TestService: public BnTestService {  public:   TestService();   ~TestService();   void test(); }; TestService::TestService() { } TestService::~TestService() { } void TestService::test() {  printf("hello test\n"); }} int main() {  sp < ProcessState > proc(ProcessState::self());  sp < IServiceManager > sm = defaultServiceManager();  sm->addService(String16("service.testservice"), new TestService());  ProcessState::self()->startThreadPool();  IPCThreadState::self()->joinThreadPool();  return 0; }
其中声明并实现binder实体类BnInterface是如下代码实现的,定义在Test.h文件中,定义如下:
class BnTestService: public BnInterface<ITestService> {  public:  virtual status_t  onTransact(uint32_t code, const Parcel& data, Parcel* reply,   uint32_t flags = 0);  virtual void test()  {   printf("Now get test\n");  } };

BnInterface也是binder核心库和框架中的类,表示binder实体类,在onTransact函数里,会根据客户端提交的操作代码调用不同的函数,而操作代码就是2)里声明的枚举值,在本实例里是TEST,我们收到test后会调用test方法。本实例里将onTransact的实现放在下面的代码中实现:
     IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService"); status_t BnTestService::onTransact(uint_t code, const Parcel& data,  Parcel* reply, uint32_t flags) {  switch (code) {  case TEST: {   printf("got the client msg\n");   CHECK_INTERFACE(ITest, data, reply);   test();   reply->writeInt32(100);   return NO_ERROR;  }   break;  default:   break;  }  return NO_ERROR; }

在这里的onTransact调用了test()方法。
7)最后是执行,查看结果
将TestServer和TestClient推到/data/local/tmp,并修改权限 adb push TestServer /data/local/tmp adb push TestClient /data/local/tmp adb shell chmod 755 /data/local/tmp/* 然后开两个cmd窗口测试:









   





更多相关文章

  1. Android(安卓)Activity启动(二) App内部activity跳转过程及原理
  2. LinearLayout和RelativeLayout绘制过程的对比
  3. Android(安卓)利用 APT 技术在编译期生成代码
  4. Android(安卓)ListView的背景和黑色边缘化的问题
  5. 利用ActivityInstrumentationTestCase2测试Activity
  6. Android工程编译时报 Error running app: Default Activity not
  7. Android(安卓)JNI开发入门之一
  8. Android开发者编码风格
  9. android开发之Parcelable使用详解

随机推荐

  1. Android渐变色xml文件
  2. ch024 Android BroadCastReceiver
  3. android 获取手机的所有程序和widget的包
  4. Android 透明度对应16进制值
  5. Android Theme 样式 展示
  6. android 随手记-画虚线
  7. Android 允许权限
  8. android中文字跑马灯效果
  9. Android日期时间格式国际化
  10. android 颜色值 xml