当前位置:首页 » 安卓系统 » androidipc通信

androidipc通信

发布时间: 2023-04-18 15:15:40

⑴ android 组件间、进程间数据传输和限制

1、Bunder 传递对象为什么需要序列化?

1》因为 bundle 传递数据时只支持基本数据类型,所以在传递对象时需要序列化转

换成可存储或可传输的本质状态(字节流)。序列化后的对象可以在网络、IPC

(比如启动另一个进程的 Activity、Service 和 Reciver)之间进行传输,也可以 存储到本地。

2》序列化,表示将一个对象转换成可存储或可传输的状态。序列化的原因基本三种 情况:

1.永久性保存对象,保存对象的字节序列到本地文件中; 2.对象在网络中传递;

3.对象在 IPC 间传递。

2、序列化Serializable 和Parcelable 的区别
Serializable(java 自带):

1》Serializable 是序列化的意思,表示将一个对象转换成存储或可传输的状态。序列化后的对象可以在网络上进传输,也可以存储到本地。

2》Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作。

Parcelable(android 专用):

1》除了 Serializable 之外,使用 Parcelable 也可以实现相同的效果,不过不同于将 对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是 Intent 所支持的数据类型,这也就实现传递对象的功能 了。

2》Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作不需要用反 射,数据也存放在 Native 内存中,效率要快很多。

两者最大的区别在于 存储媒介的不同,Serializable 使用 I/O 读写存储在硬盘 上,而 Parcelable 是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先选择 Parcelable。

3、bundle传输的数据是否有限制,是多少,为什么要限制?

1》Intent 在传递数据时是有大小限制的,大约限制在 1MB 之内,你用 Intent 传递 数据,实际上走的是跨进程通信(IPC),跨进程通信需要把数据从内核 到进程中,每一个进程有一个接收内核数据的缓冲区,默认是 1M;如果一次传 递的数据超过限制,就会出现异常。

2》不同厂商表现不一样有可能是厂商修改了此限制的大小,也可能同样的对象在不 同的机器上大小不一样。

3》传递大数据,不应该用 Intent;考虑使用 ContentProvider 或者直接匿名共享内 存。简单情况下可以考虑分段传输。

4、匿名共享内存(https://www.jianshu.com/p/d9bc9c668ba6)

⑵ Android的IPC机制

IPC是内部进程通信的简称, 是共享”命名管道”的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。

⑶ android 进程间的通信(IPC)方式有哪些

Android为了屏蔽进程的概念,利用不同的组件[Activity、Service]来表示进程之间的通信!组件间通信的核心机制是Intent,通过Intent可以开启一个Activity或Service,不论这个Activity或Service是属于当前应用还是其它应用的。
一、Intent包含两部分:
1、目的[action]--要往哪里去
2、内容[category、data]--路上带了些什么,区分性数据或内容性数据
二、Intent类型:
1、显式--直接指定消息目的地,只适合同一进程内的不同组件之间通信
new Intent(this,Target.class)
2、隐式--AndroidMainifest.xml中注册,一般用于跨进程通信
new Intent(String action)

IPC机制:有了Intent这种基于消息的进程内或进程间通信模型,我们就可以通过Intent去开启一个Service,可以通过Intent跳转到另一个Activity,不论上面的Service或Activity是在当前进程还是其它进程内即不论是当前应用还是其它应用的Service或Activity,通过消息机制都可以进行通信!

⑷ Android跨进程通信

本文整理和引用他人的笔记,旨在个人复习使用。

参考链接:

https://blog.csdn.net/fanleiym/article/details/83894399

https://github.com/274942954/AndroidCollection/blob/master/Docs/Android%E7%9F%A5%E8%AF%86%E7%82%B9%E6%B1%87%E6%80%BB.md#%E8%BF%9B%E7%A8%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F

https://www.kaelli.com/4.html

https://carsonho.blog.csdn.net/article/details/73560642?utm_medium=distribute.pc_relevant.none-task-blog--1.e_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog--1.e_weight

默认情况下,一个app只会运行在一个进程中,进程名为app的包名。

1. 分散内存的占用

Android系统对每个应用进程的内存占用是有限制的,占用内存越大的进程,被系统杀死的可能性就越大。使用多进程可以减少主进程占用的内存,避免OOM问题,降低被系统杀死的概率。

2. 实现多模块

一个成熟的应用一定是多模块化的。项目解耦,模块化,意味着开辟新的进程,有独立的JVM,带来数据解耦。模块之间互不干预,团队并行开发,同时责任分工也很明确。

3. 降低程序奔溃率

子进程崩溃不会影响主进程的运行,能降低程序的崩溃率。

4. 实现一些特殊功能

比如可以实现推送进程,使得主进程退出后,能离线完成消息推送服务。还可以实现守护进程,来唤醒主进程达到保活目的。还可以实现监控进程专门负责上报bug,进而提升用户体验。

android:process 属性的值以冒号开头的就是 私有进程 ,否则就是 公有进程 。当然命名还需要符合规范,不能以数字开头等等。

1. 前台进程

2. 可见进程

3. 服务进程

4. 后台进程

5. 空进程

Android 会将进程评定为它可能达到的最高级别。另外服务于另一进程的进程其级别永远不会低于其所服务的进程。

创建新的进程时会创建新的Application对象,而我们通常在Application的onCreate方法中只是完成一些全局的初始化操作,不需要多次执行。

解决思路:获取当前进程名,判断是否为主进程,只有主进程的时候才执行初始化操作

获取当前进程名的两种方法:

Application中判断是否是主进程(方法1例子):

Serializable 和 Parcelable是数据序列化的两种方式,Android中只有进行序列化过后的对象才能通过intent和Binder传递。

通常序列化后的对象完成传输后,通过反序列化获得的是一个新对象,而不是原来的对象。

Serializable是java接口,位于java.io的路径下。Serializable的原理就是把Java对象序列化为二进制文件后进行传递。Serializable使用起来非常简单,只需直接实现该接口就可以了。

Parcelable是Google为了解决Serializable效率低下的问题,为Android特意设计的一个接口。Parcelable的原理是将一个对象完全分解,分解成可以传输的数据类型(如基本数据类型)再进行传递。

通常需要存到本地磁盘的数据就使用Serializable,其他情况就使用效率更高的Parcelable。

IPC 即 Inter-Process Communication (进程间通信)。Android 基于 Linux,而 Linux 出于安全考虑,不同进程间不能之间操作对方的数据,这叫做“进程隔离”。

每个进程的虚拟内存空间(进程空间)又被分为了 用户空间和内核空间 进程只能访问自身用户空间,只有操作系统能访问内核空间。

由于进程只能访问自身用户空间,因此在传统的IPC中,发送进程需要通过_from_user(系统调用)将数据从自身用户空间拷贝到内核空间,再由接受进程通过_to_user从内核空间复拷贝到自身用户空间,共需要拷贝2次,效率十分低下。Android采用的是Binder作为IPC的机制,只需复制一次。

Binder翻译过来是粘合剂,是进程之间的粘合剂。

Binder IPC通信的底层原理是 通过内存映射(mmap),将接收进程的用户空间映射到内核空间 ,有了这个映射关系,接收进程就能通过用户空间的地址获得内核空间的数据,这样只需发送进程将数据拷贝到内核空间就可完成通讯。

一次完整的Binder IPC通信:

从IPC的角度看,Binder是一种跨进程通信机制(一种模型),Binder 是基于 C/S 架构的,这个通信机制中主要涉及四个角色:Client、Server、ServiceManager和Binder驱动。

Client、Server、ServiceManager都是运行在用户空间的进程,他们通过系统调用(open、mmap 和 ioctl)来访问设备文件/dev/binder,从而实现与Binder驱动的交互。Binder驱动提供进程间通信的能力(负责完成一些底层操作,比如开辟数据接受缓存区等),是Client、Server和ServiceManager之间的桥梁。

Client、Server就是需要进行通信两个的进程,通信流程:

细心的你一定发现了,注册服务和获得服务本身就是和ServiceManager进行跨进程通信。其实和ServiceManager的通信的过程也是获取Binder对象(早已创建在Binder驱动中,携带了注册和查询服务等接口方法)来使用,所有需要和ServiceManager通信的进程,只需通过0号引用,就可以获得这个Binder对象了。

AIDL内部原理就是基于Binder的,可以借此来分析Binder的使用。

AIDL是接口定义语言,简短的几句话就能定义好一个复杂的、内部有一定功能的java接口。

先看看ICallBack.aidl文件,这里定义了一个接口,表示了服务端提供的功能。

被定义出来的java接口继承了IInterface接口,并且内部提供了一个Stub抽象类给服务端(相当于封装了一下,服务端只需继承这个类,然后完成功能的里面具体的实现)。

参考: https://www.cnblogs.com/sqchen/p/10660939.html

(以下是添加了回调的最终实现,可以看参考链接一步一步来)

为需要使用的类,创建aidl文件。

系统会自动在main文件下生成aidl文件夹,并在该文件夹下创建相应目录。

在java相同路径下创建Student类,这里不能使用@Parcelize注解,否则会报错

创建IStudentService.aidl,定义了一个接口,该接口定义了服务端提供的功能。创建完后rebuild一下项目 (每次创建和修改定义接口文件都要rebuild一下)

创建在服务端的StudentService

可以看见有回调,说明客户端也提供了接口给服务端来回调(双向通信,此时客户端的变成了服务端),即ICallBack.aidl

客户端是通过Binder驱动返回的Binder调用StudentService里的具体实现方法

AIDL使用注意:

Messenger可以在不同进程中传递 Message 对象,在Message中放入我们需要传递的数据,就可以轻松地实现数据的进程间传递了。Messenger 是一种轻量级的 IPC 方案,是对AIDL的封装,底层实现是 AIDL。

使用详见: https://blog.csdn.net/qq951127336/article/details/90678698

⑸ Android-IPC

IPC是Inter-Process Communication的缩写,含义就是跨进程通信。
首先我们要理解什么是进程,什么是线程。按敬宏或操作系统的描述,进程是资源分配的最小单位,而线程是CPU调度的最小单位,一个进程可亮伍以包含多个线程(主线程、子线程)。多线程需要考虑并发问题。
Android中的主线程是也叫UI线程,在主线程执行耗时绝迹操作会ANR。

主要包含三部分:Serialiazable,Parcelable以及Binder

Serialiazable与Parcelable的区别:Serialiazable使用简单但是需要大量I/O操作,Parcelable使用较繁琐,主要用于内存序列化,效率高。

⑹ 02 项目架构-IPC通信框架

Android App开发中的IPC(进程间通信)无处不在。比如我们使用的 AlarmManager 、 InputMethodService 都是系统为我们提供的服务,处于单独的进程中。如果需要在自己的App进程中使用这些服务就需要进行IPC通信。

除此之外,我们自己的程序中也会存在进程通信的可能(特别是在一些大型APP中)

QQ:未登陆

微信:使用一段时间后:

场景:在Service中开启定位服务,Service处于单独的进程,需要在App主进程或者其他APP中获得定位结果。

服务中提供暴露给其他进程使用的方法并提供一个 ServiceId 注解标记,而服务实现中必须给到相同的 ServiceId 与方法实现,不强制要求 LocationManager 一定需要继承 ILocationManager j接口,但是为了保证方法签名统一建议继承。(不然一个是getLocation,另一个是getLocation2就不好玩了)

在Service进行定位,定位结果在 LocationManager 中记录。在这个Service中使用框架注册 LocationManager 。

不需要返回 Binder 对象,这意味着使用者不需要编写繁琐没任何提示的AIDL文件。

框架内部会提供 com.enjoy.ipc.IPCService$IPCServiceX 多个预留Service,用于与其他进程通信,如果一个App存在多个进程都需要提供各自进程的服务,可以使用不同的Service。所以本质上依然是借助的Service+Binder通信,但框架将细节封装隐藏,使用更加简单。

获得结果对象后就能像调用本地方法一样调用远程方法(RPC调用)。

在使用中简化了:

1、不需要自己定义AIDL接口,使用的JavaBean也不要求实现 Parcelable 接口;

2、在客户端不需要直接使用 bindService 获得 Binder 对象;

服务端需要定义暴露服务的接口(ILocationManager),客户端如果是其他APP,则需要将接口类放到自己的源码中(不需要接口实现)。接口中定义的方法就是服务端提供给其他进程使用的方法。

整个框架包含了服务端与客户端两端接口。

在服务进程中会缓存 ServiceId 与对应的服务实现Class对象: 服务表 ,同时服务实现中的所有方法列表也需要进行记录: 方法表 。由于一个服务中可能存在多个方法,所以其数据结构为 Map<Class,Map<String,Method>> ,外层 Map 的key为服务Class,内层 Map 的key则为方法标记。

当客户端需要调用服务时,将 ServiceId 、MethodName以及执行方法需要的参数传递给服务端,服务端查表利用反射 Method#invoke 即可执行服务中的方法。

其中客户端的请求被封装为 Request 对象,服务端响应则封装为 Response 对象

服务端只需要暴露服务接口给其他进程使用,所以服务端只需要调用框架的注册接口 regiest 对服务实现进行注册。( 注册的是服务实现,而不是服务接口 )

注册时,通过反射获得Class上的 ServiceId 即可记录 服务表 。同时利用反射获得Class中所有的public Method即可记录 方法表

由于框架本质还是利用Binder来完成通信,为了与其他进程通信,框架内部提供了多个预留的Service。

通信Service会返回一个AIDL生成的Binder类对象

客户端使用 send 方法向服务端发起请求。

服务端接收到请求后的实现:

客户端需要先与服务端建立连接,因此框架中提供了 connect 方法,内部封装 bindService 实现与服务端通信Service( IPCService )的绑定。

唯一需要注意的是:

当完成绑定后,客户端就可以获得服务端通信Service提供的 IIPCService 对象,客户端调用 IIPCService#send 发起请求。

当我们需要获得 Location 。则应该调用 LocationManager.getDefault().getLocation() 。这句调用会需要执行 LocationManager 的两个方法: getDefault 与 getLocation 。

然而这个对象存在服务端,客户端如何获得?

我们可以利用动态代理,在客户端创建一个 "假的" 服务接口对象(代理)。

当我们执行这个代理对象的方法( getLocation )时,会回调 IPCInvocationHandler#invoke 方法,在这个方法中框架会向服务端发起请求: IIPCService#send

而 getLocation 会返回一个 Location 记录定位信息的对象,这个对象会被服务端json序列化发送过来,因此,客户端只需要在此处获得 Method 的返回类型并反序列化即可。

RPC指的是:从客户端上通过参数传递的方式调用服务器上的一个函数并得到返回的结果,隐藏底层的通讯细节。在使用形式上像调用本地函数一样去调用远程的函数。

比如我们使用Okhttp进行网络请求:

这种方式很显然不是RPC。

而使用Retrofit:

RPC:我们调用远程的XXX方法,就像在调用本地方法一样。

⑺ Android IPC机制

IPC是指两个进程之间进行数据交互的过程,即:跨进程通信。
进程是一个执行单,在移动设备上指一个程序或者一个应用。一个进程可以有多个线程,也可以只有一个线程,即主线程。在Android里边,主线程也叫作UI线程,要是在主线程执行大量耗时任务,就会造成界面无法响应,ANR问题,解决这类问题,把耗时操作放在子线程就好。
在Android中,最有特色的进程间通信就是Binder,Binder轻松的实现了进程间的通信。

给四大组件 Activity、Service、Receiver、ContentProvider 在AndroidMenifeist中指定 android:process 属性,可以指定其运行的进程。
: 开头的线程是当前应用的私有进程,其它应用不可以和它跑在同一个进程中,而不以 : 开头的属于全局进程,其他应用通过ShareUID方式可以和它跑在一个进程中。

Android为了每一个应用(进程)都分配了独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间。
多进程会造成如下几个反面方面的问题:

为了解决这些问题,系统提供了跨进程通信方法,虽然不能直接共享内存,但是可以实现数据共享。Intent来传递数据,共享文件,基于Binder的Messenger,ContentProvider,AIDL和Socket。

当我们需要通过Intent和Binder传输数据,或者我们需要把对象持久化到存储设备上,再或者通过网络传输给其它客户端时,Serializable和Parcelable接口可以完成对象的序列化过程。

Serialzable是java提供的序列化接口,是一个空接口,为对象同序列化和反序列化操作。
想让一个类对象实现序列化,只需要这个类实现Serialzable接口,并声明一个serialVersionUID即可,serialVersionUID可以声明成1L或者IDE根据当前类接口自动生成它的hash值。
没有serialVersionUID不影响序列化,但是可能会影响反序列化。序列化时,系统当前类的serialVersionUID写入序列化文件中,当反序列化时,回去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果不一致,无法完成反序列化。

Seriallizable用起来简单但是开销大,序列化和反序列过程需要大量的I/O操作,而Parcelable是Android序列化方式,更适合Android平台,效率更高。Parcelable主要用于内存序列化上,而Seriallizable更适用于序列化到本地存储设备,或者将对象序列化后通过网络传输到别的客户端。

Activity、Service、Receiver都支持在 Intent中传递Bundle数据,Bundle实现了Pareclable接口,所以它可以方便地在不同进程间传输。

Android基于Linux,使得其并发读写文件可以没有限制的进行,两个进程可以通过读写一个文件来交换数据。共享数据对文件格式没有要求,双反约定就行。使用文件共享很有可能出问题。
SharedPreferences是个特例,虽然也是属于文件的一种,但是由于系统对它的读写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对他的读写变得不可靠,高并发的时候,很大可能会丢失数据。

Messenger可以在不同的进程中传递Message对象,在Message中存入我们需要传递的数据,就可以实现数据的跨进程传递。它是一种轻量级的IPC方案,底层实现是AIDL。
Messenger对AIDL做了封装,使得我们可以更便捷的实现跨进程通信,它一次只处理一个请求,在服务端不用考虑线程同步问题,在服务端不存在并发执行的情形。实现一个Messenger有如下几个步骤:

在服务端创建一个Service,同时创建一个Handler,并通过它来创建一个Messenger对象,然后再Service的onBind中返回这个Messenger对象底层Binder即可。

绑定服务端Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger。通过这个对象就可以向服务端发消息了。如果需要服务端回应客户端,就需要和服务端一样,创建一个Handler,并通过它来创建一个Messenger对象,然后把这个Messenger对象通过Message的replyTo参数传给服务端,服务端可以通过这个replyTo参数回应客户端。

首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现AIDL接口即可。

绑定服务端的Service,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可可以范文AIDL里边的方法了。

在AIDL文件中,并不是所有的额数据类型都是可以使用的。

以上6种数据就是AIDL所支持的所有类型,其中自定义的Parecelable对象和AIDL对象必须显示的import,不管是否和当前的AIDL文件位于同一个包。
AIDL文件中用到了自定义的Parcelable对象,必须新建一个同名的AIDL文件,在其中声明它为parcelable类型。
AIDL中除了基础数据类型,其它类型参数都需要标上方向:in、out、inout,in是输入型参数,out是输出型参数,inout是输入输出型参数。

上面是远程服务端示例,AIDL方法在服务端的Binder线程池中执行,因此各个客户端同时连接的时候,会存在多个线程同时访问的情形,所以要在AIDL中处理线程同步,这个CopyOnWriteArrayList支持并发的读写。
AIDL所支持的是一个抽象的List,只是一个接口,因此虽然服务端返回的是CopyOnWriteArrayList,当时Binder会按照List规范去范文数据并最终形成一个ArrayList传递给客户端。

ServiceConnection 的回调方法在UI线程中运行,服务端的方法有可能很久才能执行完毕,需要考虑ANR的问题。
服务的方法本省就运行再Binder线程池中,本身可以执行大量耗时操作,不要去服务端方法中开县城去进行异步任务。

客户端

服务端

RemoteCallbackList是系统提供专门用于删除跨进程listener的,它的内部有一个Map结构,用来保存所有的AIDL回调,这个Map的key就是Binder类型,value是CallBack类型。
客户端解注册的时候,我们只需要遍历服务端所有的listener,找出那个和接注册listener具有相同的Binder对象的服务端listener并把它删除即可。
RemoteCallbackList的beginBroadcast和finishBroadcast必须配对使用。

ContentProvider是Android专门提供不同应用间进行数据共享的方式。底层实现一样是Binder。
系统预置了许多ContentProvider,比如通讯录,日程信息表,只需要通过ContentResolver的query、update、insert、delete方法即可。

⑻ 安卓IPC跨进程通讯:AIDL+Retrofit——AndLinker的初步使用

需要用到安卓跨进程通讯,明指IPC (进程间通信) 的时候,AndLinker是一款Android上的IPC (进程间通信) 库,结合了 AIDL 和 Retrofit 的诸多特性,且可以与 RxJava 和 RxJava2 的Call Adapters无缝结合使用。

个人简单理解就是:简化AIDL流程的一个第三方库。使用时斗昌需要先了解一下AIDL、retrofit。

以普通Java接口代替AIDL接口

像 Retrofit 一样生成远程服务接口的IPC实现

支持的Call Adapters:Call, RxJava  Observable, RxJava2  Observable & Flowable

支持远程服务回调机制

支持AIDL的所有数据类型

支持AIDL的所有数据定向tag:in,out,inout

支持AIDL的oneway关键字

在服务端以及客户端的项目根目录的build.gradle中添加jcenter()仓库

在App的build.gradle中添加如下依赖

AndLinker支持AIDL所有数据类型:

Java语言中的所有原始类型 (如:int,long,char,boolean,等等)

String

CharSequence

Parcelable

List (List中的所有元素必须是此列表中支持的数据类型)

Map (Map中的所有元素必须是此列表中支持的数据类型)

接口里的方法就是按需激销配求需创建。这里只举几个简单的示例。

热点内容
linux485 发布:2025-07-05 14:38:28 浏览:293
php用的软件 发布:2025-07-05 14:06:22 浏览:745
没有权限访问计算机 发布:2025-07-05 13:29:11 浏览:418
javaweb开发教程视频教程 发布:2025-07-05 13:24:41 浏览:666
康师傅控流脚本破解 发布:2025-07-05 13:17:27 浏览:227
java的开发流程 发布:2025-07-05 12:45:11 浏览:669
怎么看内存卡配置 发布:2025-07-05 12:29:19 浏览:271
访问学者英文个人简历 发布:2025-07-05 12:29:17 浏览:821
1970linux 发布:2025-07-05 12:12:43 浏览:109
解压挑刺 发布:2025-07-05 12:12:12 浏览:537