Android跨进程通信

 我来答
科创17
2022-06-27 · TA获得超过5853个赞
知道小有建树答主
回答量:2846
采纳率:100%
帮助的人:167万
展开全部

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

参考链接:

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-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_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中,发送进程需要通过copy_from_user(系统调用)将数据从自身用户空间拷贝到内核空间,再由接受进程通过copy_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

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
Storm代理
2023-07-25 广告
StormProxies是一家可靠的代理服务提供商,提供原生IP(住宅原生IP)和高匿名代理服务。以下是关于StormProxies的原生IP服务的一些信息:1. 住宅原生IP:StormProxies提供的住宅原生IP是指从真实的家庭或企... 点击进入详情页
本回答由Storm代理提供
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式