系统相关
首页 > 系统相关> > andorid进程通信

andorid进程通信

作者:互联网

好久没写bolg,又一个新的学期,这次写一篇关于android进程间通信的总结。

android进程间通信的方式

  1. 通过共享文件实现
  2. 通过AIDL
  3. 通过Binder
  4. 通过Handler messenger机制
  5. 通过ContentProvicer
  6. 通过Socket

基本上安卓上的进程间通信就以上几种,需要说明的是,2,4,5都是基于Binder实现的。 而他们的优缺点分别是:

名称 优点 缺点 应用场景
Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件的进程间通信
文件共享 简单易用 不适合高并发场景,无法做到进程间的及时通信 没有并发的情形,交换简单的数据
AIDL 功能强大,支持一对多的并发通信,支持实时通信 使用稍复杂,需要处理好线程同步 一对多通信且有RPC需求
Messager 功能一般,支持一对多的串行通信,支持实时通信 不能很好处理并发现象,并不支持RPC,只能传输Bundle支持的数据类型 低并发的一对多即时通信,无RPC需求
ContentProvider 数据访问方面功能强大,支持一对多并发数据共享 收约束的AIDL,主要提供数据源的CRUD操作 一对多的进程间数据共享
Socket 功能强大,可通过网络传输字节流,支持一对多的并发实时通信 繁琐,不支持直接的RPC 网络数据交换

RPC:Remote Procedure Call (远程过程调用) 调用另一台计算机上的程序。

文件

这个就不说了,就是不同进程读写相同的文件,不过要注意避免同时写,在写的时候加锁。

AIDL

AIDL 全程Android Interface Define Language 是Android 提供的一种进程间通信(IPC)机制,可以用它定义客户端和服务端进程间通信时候的接口,它包装了Binder的使用,通过这种机制,我们只需要写好AIDL接口文件,编译时系统会帮我们生成Binder接口。

Binder支持的4种数据:

  1. Java的基本数据类型
  2. List和Map(元素必须是AIDL支持的数据类型,Server端具体的类必须是ArrayList或者HashMap)
  3. 其他AIDL生成的接口
  4. 实现Parcelable的实体,

AIDL 的编写主要为以下三部分:

创建 AIDL 创建要操作的实体类,实现 Parcelable 接口,以便序列化/反序列化 新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件 Make project ,生成 Binder 的 Java 文件 服务端 创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法 在 onBind() 中返回 客户端 实现 ServiceConnection 接口,在其中拿到 AIDL 类 bindService() 调用 AIDL 类中定义好的操作请求

自动生成的java文件继承了IInterface,而且还包含一个抽象类Stub,是一个Binder,实现AIDL接口。 IInterface 类型的接口,包括: Stub 抽象类 aidl 接口定义的操作方法 Stub ,是一个 Binder,同时也是一个 IInterface,包括: 将 Binder 转成 IInterface 的 asInterfa 大专栏  andorid进程通信ce() 方法 处理调度的 onTransact() 方法 用于在 onTransact() 中标识要进行的操作的两个标志 一个 IInterface 类型的代理 Proxy, IInterface 类型的代理,包括: 接口定义方法的伪实现,实际调用的是真正的 Binder 的方法

Binder机制

Binder继承自IBinder,IBinder是一个接口,代表跨进程传输的能力。(IBinder 是高性能、轻量级远程调用机制的核心部分,它定义了远程操作对象的基本接口。)

在Binder机制中Client发起IPC请求时会将请求数据从用户空间拷贝到内核空间(在Binder驱动的帮助下),驱动程序再将内核空间中的数据写到Service中。而ServerManager负责Service的注册和查询。

Messenger

Messenger 的使用需要结合 Handler, Message, Bundle 。 创建客户端的 Messenger,传递一个 Handler 处理消息 bindService,在 ServiceConnection 回调中拿到服务端的 Messenger 发送消息 Message.obtain() 消息池里获取一个空闲消息对象 使用 message.setData(bundle) 设置数据 指定回信的信使 message.replyTo = mClientMessenger 调用服务端信使,发射!mServerMessenger.send(message)

Messenger 对 AIDL 进行了封装,也就是对 Binder 的封装,我们可以使用它的实现来完成基于消息的跨进程通信,就和使用 Handler 一样简单。

ContentProvider

主要方法: onCreate():初始化 provider query():查询数据 insert():插入数据到 provider update():更新 provider 的数据 delete():删除 provider 中的数据 getType():返回 provider 中的数据的 MIME 类型

ContentProvider可以提供多种不同的数据类型: int long double float BLOB:作为 64KB 字节的数组的二进制大型对象

Socket

TCP 或者 UDP 的报文中,除了数据本身还包含了包的信息,比如目的地址和端口,包的源地址和端口,以及其他附加校验信息。 由于包的长度有限,在传输的过程中还需要拆包,到达目的地后再重新组合。 如果有丢失或者损坏的包还需要重传,有的在到达目的地后还需要重新排序。 这些工作是复杂且与业务无关的,Socket 为我们封装了这些处理工作。 Socket 被称为“套接字”,它把复杂的 TCP/IP 协议簇隐藏在背后,为用户提供简单的客户端到服务端接口,让我们感觉这边输入数据,那边就直接收到了数据,像一个“管道”一样。

使用 TCP 通信的 Socket 流程 服务端: 调用 ServerSocket(int port) 创建一个 ServerSocket,绑定到指定端口 调用 accept() 监听连接请求,如果客户端请求连接则接受,返回通信套接字 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发 关闭套接字 客户端: 调用 Socket() 创建一个流套接字,连接到服务端 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发 关闭套接字

使用 UDP 通信的 Socket 流程 服务端: 调用 DatagramSocket(int port) 创建一个数据报套接字,绑定到指定端口 调用 DatagramPacket(byte[] buf, int length) 建立一个字节数组,以接受 UDP 包 调用 DatagramSocket 的 receive() 接收 UDP 包 调用 DatagramSocket.send() 发送 UDP 包 关闭数据报套接字 客户端: 调用 DatagramSocket() 创建一个数据报套接字 调用 DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port) 建立要发送的 UDP 包 调用 DatagramSocket 的 receive() 接收 UDP 包 调用 DatagramSocket.send() 发送 UDP 包 关闭数据报套接字

标签:调用,Socket,AIDL,通信,接口,进程,Binder,andorid,接字
来源: https://www.cnblogs.com/liuzhongrong/p/12251085.html