怎么写一个native层的service

本文介绍如何在Android中创建一个Native层的Service,通过示例详细解释了bin可执行文件的编写及Test类的具体实现过程,包括如何与Service Manager交互并提供持续服务。

http://www.myexception.cn/mobile/1852861.html


如何写一个native层的service

android的service大概有这么几种形式,Java service ,native service,或者Java层通过某种通信方式比如socket和demon交互. 
Java层的aidl很方便,写socket的demon方式也很好理解,native的就显得稍微麻烦一点,咱们通过一个例子来说一下,首先说我们不讲解binder的内部机制…. 
我们打算写个简单的service,只提供set和get方法 
1. 先写一个bin 的可执行文件

int main(int argc, char** argv)   
{    
signal(SIGPIPE, SIG_IGN);    
sp<ProcessState> proc(ProcessState::self());    
sp<IServiceManager> sm = defaultServiceManager();    
ALOGI("ServiceManager: %p", sm.get());    
sm->addService(String16("service.test"),new Test ());    
IPCThreadState::self()->joinThreadPool();   
}


sp<IServiceManager> sm = defaultServiceManager(); 

我们实际得到了servicemanager的binder proxy,通过这个接口我们可以调用servicemanager的方法addservice. 

sm->addService(String16("service.test"),new Test ()); 

把我们提供的bbinder提供给servicemanager,前面的那个名字必须是唯一的. 

IPCThreadState::self()->joinThreadPool(); 

有了joinThreadPool以后,我们就可以持续的提供服务了.

2 看一下test这个类的实现 
test.h

class Test : public BnTest{  
public:  
    inline uint32_t  getTest(){  
        ALOGD("getTest===== %d",IPCThreadState::self()->getCallingUid());   
        return value;  
    }  
    inline void setTest(uint32_t par){  
        ALOGD("setTest===== %d",IPCThreadState::self()->getCallingUid());  
        value = par;  
    }  
private:  
    uint32_t value;  
};  

我们的test类是继承了BnTest,它是具体的干活的类

ITest.h

class ITest : public IInterface{

public:
    DECLARE_META_INTERFACE(Test);
    virtual uint32_t getTest() = 0;
    virtual void setTest(uint32_t ) = 0;
};
class BnTest : public BnInterface<ITest>{

    public:
        virtual status_t  onTransact(uint32_t code,
                              const Parcel& data,
                              Parcel* reply,
                              uint32_t flags= 0 );

};  

ITest就相当于是aidl的接口定义了 
ITest.cpp

enum{
GET_Test = 1,
SET_Test,
};
class BpTest: public BpInterface<ITest>{
    public:
    BpTest(const sp<IBinder>& impl)
        : BpInterface<ITest>(impl){
    }

    virtual uint32_t getTest(){
        Parcel data,reply;
        data.writeInterfaceToken(ITest::getInterfaceDescriptor());
        remote()->transact(GET_Test,data,&reply);
        return reply.readInt32();

    }
    virtual void setTest(uint32_t params){
        Parcel data,reply;
        data.writeInterfaceToken(ITest::getInterfaceDescriptor());
        data.writeInt32(params);
        remote()->transact(SET_Test,data,&reply);
        return;

    }


};
IMPLEMENT_META_INTERFACE(Test,"android.Test.ITest");

status_t BnTest::onTransact(uint32_t code,
                        const Parcel& data,
                        Parcel* reply,
                        uint32_t flags){
    switch(code){
    case GET_Test:{
        CHECK_INTERFACE(ITest,data,reply);
        reply->writeInt32(getTest());
        return NO_ERROR;
        }break;
    case SET_Test:{
        CHECK_INTERFACE(ITest,data,reply);
        uint32_t value = data.readInt32();
        setTest(value);

        return NO_ERROR;
        }break;
    default:
    return BBinder::onTransact(code, data, reply, flags);


}
}

而ITest几乎也是照着模板写的,Google自己肯定写了类似于aidl的工具来生成native的service.


<think>好的,我现在需要帮助用户获取一个Binder Native部分的代码示例。用户之前已经问过关于misc在IT领域中的应用,特别是提到了Android的Binder驱动使用misc设备。现在他们想了解Native的Binder代码示例,我需要结合他们提供的引用和之前的回答来构造合适的回应。 首先,回顾用户提供的引用内容。引用1和3是关于AIDL的定义和Stub类的生成,引用2是Android.mk的编译配置,引用4详细解释了Binder的跨进程通信机制,特别是asInterface方法的作用。这些引用集中在AIDL接口的实现、Binder的Stub和Proxy模式,以及Native的编译配置。 用户现在需要的是Native部分的Binder代码示例,也就是用C++编的Binder服务端和客户端的实现。根据引用2中的Android.mk文件,里面提到了LOCAL_SHARED_LIBRARIES包括libbinder,说明Native Binder需要使用这些库。而引用4中的JavaBinder机制可能需要在Native有对应的实现,比如BnInterface和BpInterface。 接下来,我需要构造一个简单的Native Binder示例。通常,Native Binder涉及定义接口、实现服务端、编客户端以及配置编译文件。首先,定义接口头文件,继承IInterface,声明方法。然后,服务端继承BnInterface,实现虚函数。客户端则通过BpInterface来调用远程方法。 需要注意的是,Native Binder的接口需要使用DESCRIPTOR来标识,类似于Java的DESCRIPTOR。在服务注册时,使用addService方法,客户端通过getService获取接口。另外,编译时需要链接libbinder等库,并配置Android.mk或CMakeLists.txt。 用户可能还关心代码的结构和关键点,比如接口定义、服务实现、客户端调用、以及Binder线程池的启动。需要确保代码示例能够展示跨进程通信的基本流程,并解释关键函数的作用,比如defaultServiceManager()、addService()、getService()等。 可能还需要提到权限问题,比如SELinux策略是否需要调整,或者是否需要系统权限来注册服务。但在示例中可能先忽略这些,保持简单。另外,确保代码中的错误处理,比如检查getService是否成功。 最后,根据用户之前的问题,可能需要补充相关问题,引导他们进一步学习,比如如何传递复杂数据类型、多线程处理,或者与AIDL的对比。这些问题可以帮助用户深入理解Binder机制的不同面。</think>#### 一、Native Binder代码实现原理 Binder Native通过**C++接口**实现跨进程通信(IPC),核心涉及三个角色: 1. **接口定义**(继承`IInterface`) 2. **服务端实现**(继承`BnInterface`) 3. **客户端代理**(继承`BpInterface`) --- #### 二、完整代码示例(基于Android NDK) ##### 1. **接口定义** `IWeatherInterface.h` ```cpp #include <binder/IInterface.h> #include <binder/Parcel.h> class IWeatherInterface : public android::IInterface { public: DECLARE_META_INTERFACE(WeatherInterface); // 自动生成DESCRIPTOR标识符 virtual android::String16 getWeatherInfo(int64_t timestamp) = 0; // 纯虚函数声明 }; // 定义Binder代理类(客户端使用) class BpWeatherInterface : public BpInterface<IWeatherInterface> { public: explicit BpWeatherInterface(const sp<IBinder>& impl) : BpInterface<IWeatherInterface>(impl) {} android::String16 getWeatherInfo(int64_t timestamp) override { Parcel data, reply; data.writeInterfaceToken(IWeatherInterface::getInterfaceDescriptor()); data.writeInt64(timestamp); // 入参数 remote()->transact(GET_WEATHER_INFO_TRANSACTION, data, &reply); // 发起跨进程调用 return reply.readString16(); // 读取返回结果 } enum { GET_WEATHER_INFO_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION }; }; // 定义Binder本地类(服务端实现) class BnWeatherInterface : public BnInterface<IWeatherInterface> { public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override { switch(code) { case GET_WEATHER_INFO_TRANSACTION: { CHECK_INTERFACE(IWeatherInterface, data, reply); int64_t timestamp = data.readInt64(); // 解析参数 android::String16 result = getWeatherInfo(timestamp); reply->writeString16(result); // 入返回数据 return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } } }; ``` ##### 2. **服务端实现** `WeatherService.cpp` ```cpp class WeatherServiceImpl : public BnWeatherInterface { public: android::String16 getWeatherInfo(int64_t timestamp) override { // 实际业务逻辑(示例返回固定值) return android::String16("Sunny at timestamp:") + android::String16(std::to_string(timestamp).c_str()); } }; int main() { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); sm->addService(android::String16("WeatherService"), new WeatherServiceImpl()); ProcessState::self()->startThreadPool(); // 启动Binder线程池 IPCThreadState::self()->joinThreadPool(); // 进入循环等待请求 return 0; } ``` ##### 3. **客户端调用** `WeatherClient.cpp` ```cpp int main() { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(android::String16("WeatherService")); if (binder != nullptr) { sp<IWeatherInterface> service = interface_cast<IWeatherInterface>(binder); // 转换为接口 android::String16 result = service->getWeatherInfo(1625097600); __android_log_print(ANDROID_LOG_INFO, "BinderDemo", "Weather: %s", android::String8(result).c_str()); } return 0; } ``` ##### 4. **编译配置** `Android.mk` ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := WeatherService LOCAL_SRC_FILES := WeatherService.cpp IWeatherInterface.h LOCAL_SHARED_LIBRARIES := libbinder libutils liblog # 关键依赖库 include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := WeatherClient LOCAL_SRC_FILES := WeatherClient.cpp IWeatherInterface.h LOCAL_SHARED_LIBRARIES := libbinder libutils liblog include $(BUILD_EXECUTABLE) ``` --- #### 三、关键技术解析 1. **接口标识机制**: - `DECLARE_META_INTERFACE`宏生成唯一的`DESCRIPTOR`字符串(如`IWeatherInterface`) - 用于`writeInterfaceToken()`验证接口匹配性[^4] 2. **数据序列化**: - 使用`Parcel`对象的`writeInt64()/readString16()`方法处理参数 - 支持基本类型和`Parcelable`对象(需实现`flatten()`方法) 3. **线程管理**: - `startThreadPool()`启动Binder线程池(默认4个线程)[^2] - `joinThreadPool()`使主线程进入IPC处理循环 --- #### 四、运行验证步骤 ```bash # 编译部署 mm -j8 adb push WeatherService /system/bin/ adb push WeatherClient /system/bin/ # 启动服务端(需root权限) adb shell chmod 755 /system/bin/WeatherService adb shell /system/bin/WeatherService & # 客户端调用 adb shell /system/bin/WeatherClient # 输出示例: Weather: Sunny at timestamp:1625097600 ``` --- #### 五、与Java的对应关系 | Native组件 | Java对应 | 作用 | |---------------------|------------------------|-----------------------------| | `BnInterface` | `Stub` | 服务端实现基类 | | `BpInterface` | `Proxy` | 客户端代理类 | | `interface_cast<>()`| `asInterface()` | 转换IBinder为具体接口[^4] | | `Parcel` | `Parcel` | 跨进程数据容器 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值