Android实现本机应用层与linux程序通信

本人目前参与的一个项目,其Android系统是高度本地化定制的,APP上的数据主要来自本机硬件,这就需要一种机制来实现底层数据与上层APP之间进行交互。最初的想法使用JNI方式封装一个C程序库供APP调用,此种方式的好处就是APP程序相对简单,但坏处很明显:程序之间的耦合很大,未来维护与扩充比较困难,而且APP会显得庞大,运行效率不高。
既然JNI方式坏处这么明显,只能另想办法,比较常用的是采用中间件方式。基本架构就是增加一个中间件,用C实现,运行时为Linux下的一个单独进程,作为APP与底层各硬件模块之间的信使,用来传输与解析(封装)信息。
确定采用中间件方式后,首先要解决进程间通信问题。如果在应用层,APP与APP之间有多种进程间通信方式,主要是Ibinder,还有其它简单易用的,比如Intent、Broadcast、ContentProvider等,但我们要实现的是APP层与底层C进程的通信,所以不能采用应用层这些方式,首先能想到的就是采用Socket方式,虽然Socket主要是网络通信用的,但是在本机内实现进程间通信也是可以的。
现在思路很明显了,采用本机的Socket方式来实现进程间通信,我们知道Socket分为TCP与UDP,既然是本机,当然采用效率高的UDP方式。方案定下来后,就开始写demo进行验证此种方式的可行性与可靠性了。APP作为客户端,中间件作为服务器端,经过测试,发现两台机器之间,APP与中间件能通信,但是在本机内不能通信。测试时将APP装在Android模拟器上,如果中间件也运行于Android模拟器中,则不能通信,如果中间件运行于其它机器上则能进行通信。经过测试发现此种方式不可行(具体原因尚不知,希望有人能指导一下),所以采用Socket UDP方式也被排除。
最后经过研究,Android已经给出了方案,就是LocalSocket方式,此处方式不同于一般的Socket,没有TCP与UDP之分,是专门提供应用程序与Linux层通信的方式,里面封装了Socket的相关接口,使用起来也类似于Socket方式。
最后经过几次测试,终于实现了应用层与Linux层的通信,APP作为客户端,中间件作为服务器端,中间件能接收来自多个APP端的消息。
[b] 一、客户端关键代码:[/b]
1.生成LocalSocketAddress对象,传入服务名
public static final String SERVICE_NAME = "LocalSocketName";
LocalSocketAddress address = new LocalSocketAddress(SERVICE_NAME,Namespace.RESERVED);
注意:因为C程序会作为一个Socket服务随系统启动,此服务有一个服务名,所以要正确连接到服务器端,SERVICE_NAME两边要一致,同时第二个参数一定要为Namespace.RESERVED,否则连接不成功(注意:APP层也可以实现LocalSocket服务器端,主要可以用来测试客户端,如果用APP实现服务器端,测试连接时,第二个参数省略)。

2.使用LocalSocket对象主动连接服务器端
LocalSocket clientSocket = new LocalSocket();
clientSocket.connect(address);

注意:如果产生异常,比如服务不存在或LocalSocketAddress的参数不对,则连接不成功。

3.通过OutputStream发送数据
public static final String CHAR_SET = "GBK"; //字符编码格式
String sendStr = "发送给服务器端";
OutputStream outputStream = clientSocket.getOutputStream();
PrintWriter os = new PrintWriter(new OutputStreamWriter(outputStream,CHAR_SET), false);
os.print(sendStr);
if ( os.checkError() ) {
return false; //发送不成功
}
return true; //发送成功

注意:为了使中文不为乱码,应该采用GBK编码;本代码不能在UI线程中

4.通过InputStream接收来自服务器的数据
char[] dataBuf = new char[1024]; //接收数据缓存
InputStream inputStream = clientSocket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream,CHAR_SET);
int count = isr.read(dataBuf);
if (count > 0) {
System.out.println(“接收来自服务器:”+new String(dataBuf,0,count));
}

注意:为了使中文不为乱码,应该采用GBK编码;本代码不能在UI线程中


[b] 二、服务器端配置:[/b]
1.在init.rc加入LocalSocket服务
service myLocalService /system/bin/LocalSocketName
socket LocalSocketName stream 666 system system
oneshot


[b] 三、服务器端关键代码:[/b]
1.监听来自客户端的连接
#define SOCKET_NAME "LocalSocketName"
...
int fdSockt = -1;
int fd = -1;
fdSockt = android_get_control_socket(SOCKET_NAME);
if (fdSockt >= 0) {
int ret = listen(fdListen, 10);
if ( ret >=0 ) {
struct sockaddr_un addr;
socklen_t socketlen = sizeof (addr);
fd = accept(fdSockt, (struct sockaddr *) &addr, &socketlen);

}
}


2.接收来自客户端的消息
int bytenumber ;
char receiveBuff[1024];
memset(receiveBuff, 0, 1024);
if ( fd >=0 ) {
if((bytenumber = recv(fd,receiveBuff,sizeof(receiveBuff),0))>0){
printf("接收消息:%s\n",receiveBuff);
}
}


3.给客户端返回消息
char sendBuff[1024] = "发送给客户端";

if (fd >=0) {
if(send(fd,sendBuff,strlen(sendBuff),0)> 0) {
printf("发送消息:%s\n",sendBuff);
}
}


[b]四、将配置与服务器端源码编译进系统[/b]
由于LocalSocket服务需要编译进源码里才能启动,故需要加入到Android源码后编译并刷机,重启系统才能顺利运行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 Android 应用程序框架图: ![Android 应用程序框架图](https://developer.android.com/guide/platform/images/android-stack_2x.png) Android 应用程序框架是一个层次结构,其中应用程序的各个组件(如活动、服务、广播接收器和内容提供程序)通过应用程序框架与操作系统进行交互。该框架包括以下主要部分: 1. 应用程序层:该层包含应用程序组件,如活动、服务、广播接收器和内容提供程序。这些组件可以直接与用户进行交互或在后台运行。应用程序层还包括应用程序包管理器,该管理器负责安装、卸载和管理应用程序包。 2. 应用程序框架服务:该服务层提供了许多服务,如通知管理、活动管理、窗口管理和内容提供程序管理。这些服务可以由应用程序组件使用,并且它们通常是在后台运行的。 3. 核心库和运行时:该层包含 Android 运行时环境(ART)和核心 Java 库,这些库为应用程序提供了许多常用的功能,如集合、输入输出、网络和图形。此外,该层还包括 Android 系统库,这些库提供了访问 Android 操作系统的低级功能的接口。 4. 硬件抽象层(HAL):此层提供了硬件驱动程序的抽象接口,使 Android 操作系统可以与各种硬件设备进行通信,如相机、传感器和 Wi-Fi。 5. Linux 内核:该层提供了 Android 操作系统的基础,并负责管理设备驱动程序、内存管理、进程管理和网络协议栈等核心功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值