android native service编写及两个服务进程通讯

aidl 实现native service和App通信 之前一直写的是android应用之间的aidl开发,最近学习的是native service和App之间通过aidl进行通信,这里记录一下。主要介绍的是native service和App端aidl的实现,至于service的编译过程我这里没有详细的记录。我所用的android版本是11. 1、定义aidl文件 aidl文件中定义了我们想要实现的功能,是后续一切的开始,为了测试回调功能,我这里定义了一个回调接口和一个自定义数据类型FileInfo, 用来跨进程传递信息的自定义数据结构。 FileInfo.a 阅读详情
题外话:由于同事咨询,口头讲解的话1对1,但不方便多方传播及继承性,因此特意写此文章讲解一番。

1、android service简要说明:

Android Service :又称为 Java Service ,是实现在框架层里的 Service ,使用Java语言编写。
Native Service :又称为 System Service ,是实现在 Runtime 层里的 Service 。使用C++语言编写。

对于这两种service来说,两个对等service通讯都是利用binder,只不过一种利用*.aidl,一种利用IInterface
编写序列化代码而已,本质是一样的,本书先介绍native service的编写及两个native service
如何通讯的过程:

2、native service的特点
A、因为底层核心服务是 Android 框架里最接近 Linux/Driver 的部分。为了充分发挥硬件设备
   的差异化特性,核心服务是让上层 Java 应用程序来使用 Driver/HW Device 特色的重要管道。
B、在开机过程中,就可以启动核心服务 ( 例如汉字输入法服务等 ) ,让众多应用程序来共享之。
C、由于共享,所以能有效降低程序的大小及统一的接口变化 。


3、如何实现一个native service
要点如下:
a、核心服务通常在独立的进程 (Process) 里执行。
b、必须提供 IBinder 接口,让其它程序可以进行跨进程的绑定 (Binding) 和呼叫。
c、因为共享,所以必须确保多线程安全 (Thread-safe) 。
d、以 C++ 类别定义,诞生其对象,透过 SM 之协助,将该对象参考值传给 IServiceManager::addService() 函数,就加入到 Binder Driver 里了。
e、应用程序可透过 SM 之协助而远距绑定该核心服务,此时 SM 会回传 IBinder 接口给应用程序。
f、应用程序可透过 IBinder::transact() 函数来与核心服务互传数据。


下面以具体实例讲解一下具体的每个步骤如何实现完成


先说明一个测试例子的模块结构:


serviceTestA 是一个普通的过程,提供两个整数的剩法及除法运算
serviceTestB 是一个普通的过程,提供两个整数的加法及减法运算
TestService 是一个测试进程的程序,主要验证两个服务进程的接口函数,其中的代码可以
放在任何一个进程进行访问调用


a、编写服务进程

serviceTestA.h 头文件定义:


#ifndef __SERVICE_TEST_A__
#define __SERVICE_TEST_A__


#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/threads.h>


namespace android{
//继承BBinder类,从而提供IBinder 接口
class serviceTestA:public BBinder
{
public:
      serviceTestA();
virtual ~serviceTestA();
static int instantiate(); //建立唯一类实例
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);


private:
// protected by mLock 多线程安全
               mutable Mutex mLock;
};
}


#endif /* __SERVICE_TEST_A__ */


serviceTestA.cpp 实现文件:
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>


namespace android {


enum{
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM ,
};

int serviceTestA::instantiate() {
LOGI("serviceTestA instantiate");


int r = defaultServiceManager()->addService(String16("service.TestA"),
new serviceTestA());
LOGI("serviceTestA r = %d/n", r);
return r;
}


serviceTestA::serviceTestA() {
LOGI("serviceTestA created");
}


serviceTestA::~serviceTestA(){
LOGI("serviceTestA destroyed");
}


status_t serviceTestA::onTransact(uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags){
LOGI("serviceTestA::onTransact code = %d",code);
Mutex::Autolock _l(mLock);
switch(code){
case CALCULATE_MUL_NUM:{
int a = data.readInt32();
int b = data.readInt32();
int sum = a * b ;
LOGI("sum mul value = %d",sum);
reply->writeInt32(sum);
return NO_ERROR;
}break;
case CALCULATE_DIV_NUM:{
int a = data.readInt32();
int b = data.readInt32();
int sum = a / b ;
LOGI("sum div value = %d",sum);
reply->writeInt32(sum);
return NO_ERROR;
}break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
return 0;
}
}


Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES:= serviceTestA.cpp
 
LOCAL_SHARED_LIBRARIES:= libutils libutils libbinder
 
LOCAL_C_INCLUDES := $(TOP)/frameworks/base/include


LOCAL_MODULE:= libServiceTestA
 
LOCAL_PRELINK_MODULE:= false
 
include $(BUILD_SHARED_LIBRARY)


这里生成libServiceTestA动态库,方例升级服务程序


编写独立的进程程序:


它的用途是:诞生一个 serviceTestA 类别之对象,然后将该对象参考存入 Binder Driver 里。
#include <sys/types.h>
#include <unistd.h>
#include <cutils/log.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>


using namespace android;


int main(int argc,char *argv[]){
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
serviceTestA::instantiate(); // 这是重点。。。。
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}


Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES:= main.cpp
 
LOCAL_SHARED_LIBRARIES:= libutils libServiceTestA
 
LOCAL_MODULE:= serviceTestA
 
include $(BUILD_EXECUTABLE)


这里最重要的是调用:serviceTestA::instantiate();
其先执行到 new serviceTestA() ,就诞生一个 serviceTestA 类别之对象;
接着,呼叫 defaultServiceManager() 函数取得 SM 的 IServiceManager 接口;
再呼叫 IServiceManager::addService() 将该对象参考存入 Binder Driver 里,并且同时存入
到ServiceManager中注册并管理,如此其它进程才能通过ServiceManager::getService找到相应服务进程


以上代码同理,serviceTestB服务进程也一样的这样建立,不再复述。


b、测试服务进程
testService.cpp编写:
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>
#include <serviceTestB/serviceTestB.h>


using namespace android;


enum{
CALCULATE_ADD_NUM = 0,
CALCULATE_SUB_NUM ,
};


enum{
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM ,
};

int main(int argc,char *argv[]){
sp<IBinder> TestAbinder;
sp<IBinder> TestBbinder;
Parcel data, reply;
int sum=0;


LOGI("testService main is call...");


sp<IServiceManager> sm = defaultServiceManager();

while(1){
TestAbinder = sm->getService(String16("service.TestA"));
LOGE("TestA::getAddService %p/n",sm.get());
if (TestAbinder == 0) {
LOGE("TestAService not published, waiting...");
usleep(1000000);
continue;
}
else{
LOGI("TestA::getAddService success...");
break;
}
}

while(1){
TestBbinder = sm->getService(String16("service.TestB"));
LOGE("TestB::getAddService %p/n",sm.get());
if (TestBbinder == 0) {
LOGE("TestBService not published, waiting...");
usleep(1000000);
continue;
}
else{
LOGI("TestB::getAddService success...");
break;
}
}

//测试两个service中的函数
data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestAbinder->transact(CALCULATE_MUL_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_ADD_NUM value = %d",sum);

data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestAbinder->transact(CALCULATE_DIV_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_SUB_NUM value = %d",sum);

data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestBbinder->transact(CALCULATE_ADD_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_MUL_NUM value = %d",sum);

data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestBbinder->transact(CALCULATE_SUB_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_DIV_NUM value = %d",sum);

return 0;
}

这里最重要的就是通过defaultServiceManager得到默认的sm,然后通过getService得到sp<IBinder>对象,即可操作相应服务进程的接口函数,整个过程还是相当清晰的。


最后附上测试的结果打印:

# ./TestService
./TestService
# logcat
logcat
--------- beginning of /dev/log/main
I/        ( 1379): testService main is call...
E/        ( 1379): TestA::getAddService 0xa680/n
I/        ( 1379): TestA::getAddService success...
E/        ( 1379): TestB::getAddService 0xa680/n
I/        ( 1379): TestB::getAddService success...
I/        ( 1379): BpAddService::create remote()->transact()/n
I/        ( 1371): serviceTestA::onTransact code = 0
I/        ( 1371): sum mul value = 200000
I/        ( 1379): CALCULATE_MUL_NUM value = 200000
I/        ( 1379): BpAddService::create remote()->transact()/n
I/        ( 1371): serviceTestA::onTransact code = 1
I/        ( 1371): sum div value = 5
I/        ( 1379): CALCULATE_DIV_NUM value = 5
I/        ( 1379): BpAddService::create remote()->transact()/n
I/        ( 1374): serviceTestB::onTransact code = 0
I/        ( 1374): sum add value = 1200
I/        ( 1379): CALCULATE_ADD_NUM value = 1200
I/        ( 1379): BpAddService::create remote()->transact()/n
I/        ( 1374): serviceTestB::onTransact code = 1
I/        ( 1374): sum sub value = 800
I/        ( 1379): CALCULATE_SUB_NUM value = 800
结果表明完全正确

AOSP 使用AIDL添加Native Service Android自定义Native 服务 Android源码中注册服务一般有两种,一种是通过Java实现,另外一种是通过C++实现;本文介绍Native实现方式,Java实现方式请移步 [Android源码添加自定义系统服务 - Java],网上基本上也都是通过Java来自定义实现的。 阅读详情

相关推荐

安卓native service与app通过AIDL通信

android系统中native service与app位于不同的进程,可以通过AIDL进行交互传输数据。少量的数据可以用AIDL直接传输,如果是大量的数据如传输一张图片超过1M的数据话就不能用AIDL直接传了,大的数据用AIDL传输会比较慢,另外AIDL是有传输大小限制的,不适合大的数据传输。大的数据可以用共享内存来传,但注意要控制好读写共享内存时的同步问题。 native service需要添加到ServiceManager中,上层app可以通过反射获取ServiceManager连接native s

airgreen的博客 4274

Android AIDL的使用,进程间的通讯;

AIDL Android使用AIDL来实现进程间的通讯; 最简单的进程,两个APP(APP1(app_server) , APP2(app_client)),这里app_server可以看作一个进程 , app_client也可以看作一个进程; 所以AIDL可以来实现两个APP之间的通讯; 先来写一个最简单的AIDL进程间的通讯; app_client要调用app_server中的数据,首先app_server先把数据暴露出去; app_server端: 1、新建AIDL文件; 输入名..

Choi晨的博客 1303

Android添加一个Native Service

Native Service其实就是一个linux守护进程,提供一些服务,不过由于android的进程间通讯使用了Binder机制,那么我们就需要按照android的规则来实现我们的Native Service。客户端在请求service的服务时使用了一个具有相同接口的Proxy类。native service这具体实现这个接口,所以android提供了IInterface类,其是”base cla

周翔的专栏 8603

Android系统服务分析与Native Service实例

文章目录前言System ServiceVibrator 服务分析系统服务实现流程Native Service蓝牙设置实例IDeviceMac.h接口文件IDeviceMac.cpp接口实现文件DeviceMacService服务实现文件注册Service和Client端调用代码的编译与运行调用加减乘除实例IArithmeticService.hIArithmeticService.cppArithmeticService.hArithmeticService.cpp启动设置与编译运行main_client

道阻且长,行则将至 5851

从零构建:AIDL驱动Native Service与App跨进程通信实战

本文详细介绍了如何使用AIDL实现Native Service与App之间的跨进程通信,包括接口定义、服务实现、客户端连接等关键步骤。通过实战案例演示了如何构建高效可靠的IPC机制,帮助开发者掌握Android系统级开发的核心技术。

weixin_29300241的博客 377

Android下在C++环境实现native层binder服务

此文章主要目的:在Android 6.0环境下使用C++编程实现binder通讯服务端和客户端 1.在Android源码目录下存放代码树形结构 jack_server/ ├── Android.mk ├── log.h ├── service │   ├── Android.mk │   ├── JACK_Service.cpp │   └── JACK_Service.h

cyj5366的专栏 6382

安卓java端service如何在native进程进行访问-跨进程通讯高端知识

因为跨进程通讯本质上都是需要通过native端,虽然服务端或者客户端是java端,那都是先经过了native端再jni调用到java的,所以完全是可以实现客户端和服务端不要求两个都属于native或者java,完全可以native和java互通。代码1处的intTRANSACTION_getDisplayIds=2,注意这里的2就是从aidl对应的java文件中获得的,所有这个就是为啥要一定要找一个aidl文件生成的参考代码。,相信大家只要实战过马哥跨进程通讯课程肯定就对这个题目有自己的思路和方案。

learnframework的博客 1413

LBS之五:时空索引--空间邻域搜索的高效实践

时空索引的原理及最佳实践

whascj的博客 1367

跨进程C/S native service服务编写

http://blog.youkuaiyun.com/andyhuabing/article/details/7246716 纯Native的Service表示代码都在Native层,前面的文章讲到了两个service进程通过这binder中的onTransacton进行通讯,而这篇文章主要讲利用C/S结构的方法,利用IInterface进行相互访问。 以具体代码为例: test.cpp

Gabby 850

PLSQL 14.0.6 下载使用教程

众所周知,PLSQL 只是一个oracle第三方开发测试工具,它依赖oracle 客户端搭配使用,但是oracle 客户端有2G,相当庞大,不建议安装。所以我们如果下载安装好PLSQL,再下载好轻量级的支持远程链接的oracle客户端,这样搭配使用可以的话就最好了,答案是可以的。 第一步: PLSQL 下载与安装 PLSQL 14.0.6 下载地址 : https://www.allroundautomations.com/registered-plsqldev/ 下载下来,除了安装路径更改一下,

qq976511508的博客 2135

FPGA实现Gardner环定时同步:Verilog代码与Testbench实战解析

本文深入解析了在FPGA上实现Gardner环定时同步的完整过程,详细阐述了其非数据辅助的定时误差检测原理。通过Verilog代码实战,展示了内插滤波器、定时误差检测器、环路滤波器和数控振荡器等核心模块的设计,并提供了完整的Testbench验证方法,帮助开发者解决数字通信系统中的时钟同步难题。

gpt4scribbler的博客 577

native service binder

题外话:由于同事咨询,口头讲解的话1对1,但不方便多方传播及继承性,因此特意写此文章讲解一番。1、android service简要说明:Android Service :又称为 Java Service ,是实现在框架层里的 Service ,使用Java语言编写。Native Service :又称为 System Service ,是实现在 Runtime 层里的 Service 。使用C+...

doloveme的专栏 176

基于Multisim设计电子密码锁

一、设计任务与要求:(可软件仿真实现)1)基本要求:设计一个数字密码锁,要求只有按正确的顺序,输入正确的密码,方能输出开锁信号,实现开锁。设置三个正确的密码键和若干个伪键,任何伪键按下后,密码锁都无法打开。每次只能接受四次按键信号,而且第四个键只能是“确定”或者“重输键”,其他无效。能显示已输入键的个数2)扩展要求:第一次密码输错后,可以输入第二次,但是连续三次输错,密码将被锁,必须按复位键才能解锁。

ablinger的博客 4418

[Android] 使用gbinder与Android的service进行native层的IPC通讯

Android 框架是以 Binder 为基础搭建起来的,处处都离不开 Binder IPC, Android的native binder库为libbinder。其他第三方的binder库有libgbinder。

ykun089的博客 752

【Clickhouse从入门到精通】第51篇:ClickHouse权限管理体系详解

摘要 本文是ClickHouse权限管理系列文章的第51篇,重点解析ClickHouse RBAC权限体系中的GRANT/REVOKE机制。文章详细介绍了GRANT语句的基础语法与权限类型,包括SELECT、INSERT等常规权限以及WITH GRANT OPTION转授权功能。特别深入讲解了列级权限的实现方式,通过SELECT(col1,col2)语法实现字段粒度的访问控制,并展示了权限查询与验证方法。本文还对比了ClickHouse 20.4版本前后权限管理体系的差异,为构建安全的多租户数据平台提供了关

xyghehehehe的专栏 440

Adams与Matlab联合仿真入门:从零搭建你的第一个动力学模型

本文为Adams与Matlab联合仿真新手提供了一份详尽的入门指南。文章从软件环境配置、版本兼容性检查讲起,逐步演示了如何在Adams中构建单摆动力学模型并定义输入输出接口,以及在Matlab/Simulink中搭建控制回路。通过一个完整的受控单摆实例,手把手教你完成从模型导出、模块生成到执行联合仿真的全流程,帮助你快速搭建并运行第一个联合仿真模型,实现动力学与控制系统的协同验证。

g5h6i7j的博客 700

Android优化笔记--Service优化

service 是一个后台服务 专门用来处理常驻后台的工作的组件,经常会被用在及时通讯,通知等场景。 它的优化主要体现在两个方面:1.服务的保活,2.服务后台对于执行任务的集中管理. 进程的重要性优先级 1 前台进程 Foreground process 1 用户正在交互的Activity(onResume) 2 当某个Service绑定正在交互Activity 3 被主动调用为前台Service(startForeground...

ljt2724960661的博客 388

【升级U8+】不能将值 NULL 插入列 ‘VT_ID‘,表 ‘VoucherItems‘;列不允许有 Null 值。

不能将值 NULL 插入列 ‘VT_ID’,表 ‘UFDATA_006_2012.dbo.VoucherItems’;列不允许有 Null 值。INSERT 失败。

努力不懈的为广大客户提供优质的产品与真诚、贴心、专业的服务! 517
上一篇: android --- 深入理解 JNI
下一篇: 跨进程C/S native service服务编写
andyhuabing
博客等级 码龄19年 704粉丝 165原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值