Android 实现多进程通讯(如何实现多进程开发,Binder、AIDL)

目录


1)为什么App需要多进程

2)什么是多进程开发?

3)如何实现多进程开发?

4)跨进程间通讯(案例)

5)多进程需要注意什么问题?

6)多进程的底层原理是什么?【待写】



一、为什么App需要多进程?


某些应用场景下,单个进程可能无法满足需求,通过将任务分配到不同的进程中并行处理,可以提高系统整体的性能和响应速度。

在Android中,虚拟机分配给各个进程的运行内存是有限制值的,多进程app可以在系统中申请多份内存

通过创建独立的后台进程,可以确保应用在主进程被杀死或处于台时仍然能够执行一些必要的任务,如推送、消息接收等。

很多app都已经开始使用多进程,比如:推送,保活,插件化,内存不够用,webview,闹钟,电话等等。

在这里插入图片描述

二、什么是多进程开发?


多进程是指一个应用程序可以同时运行在多个独立的进程中。每个进程都有自己独立的虚拟机实例和资源管理器,并且它们之间相互隔离。一个应用可以有多个进程,就有多个dalivk虚拟机,对应多个内存空间。

默认情况下,Android应用程序在同一个进程中运行,即单进程模式。这意味着应用程序的所有组件(Activity、Service、BroadcastReceiver等)都在同一个进程中执行。但是,通过配置AndroidManifest.xml文件中的android:process属性,开发者可以为特定的组件或整个应用程序指定不同的进程名称,从而实现多进程开发。

三、如何实现多进程开发以及通讯?


默认情况下,启动一个APP,仅仅启动了一个进程,该进程名为包名,那如何定义多进程呢? Android 提供了一种方式,就是在 AndroidManifest 文件中可以通过 “android:process” 来指定进程:

  1. 不指定 process: 默认的进程,进程名为包名
  2. 指定 process,但以":"开头: 该进程为当前APP的私有进程,不允许其他APP访问
  3. 指定 process,但以小写字母开头的字符串: 该进程为全局进程 ,其他应用可设置相同的shareUID来共享该进程

场景

当应用的一部分需要高安全性或高稳定性时,比如支付模块或敏感数据处理模块。这里我将给出一个简化的案例:一个包含普通功能和支付功能的应用,我们将支付功能放在单独的进程中以提高安全性。

步骤一:定义支付进程的Service

<service  android:name=".PaymentService"  android:process=":payment"  android:exported="false" />

步骤二:创建PaymentService

public class PaymentService extends Service {  @Override  public int onStartCommand(Intent intent, int flags, int startId) {  // 接收来自其他组件的数据  String orderId = intent.getStringExtra("orderId");  // 模拟支付逻辑  boolean isSuccess = performPayment(orderId);  // 通知结果(实际开发中可能需要通过广播、AIDL等方式)  // 这里为了简化,我们假设有某种方式通知UI层  return START_NOT_STICKY;  }  private boolean performPayment(String orderId) {  // 这里实现具体的支付逻辑  // 例如调用第三方支付SDK等  return true; // 假设支付成功  }  @Override  public IBinder onBind(Intent intent) {  // 如果需要,可以返回IBinder实现IPC  return null;  }  
}

步骤三:从主进程启动PaymentService

Intent intent = new Intent(this, PaymentService.class);  
intent.putExtra("orderId", "123456789");  
startService(intent);

如果支付服务需要返回结果给主进程,或者主进程需要向支付服务发送指令,下面我们需要学习一下跨进程通信(IPC)

四、跨进程间通讯


Android中支持的多进程通信方式主要有以下几种,它们之间各有优缺点,可根据使用场景选择选择:
1)BroadcastReceiver:即广播,但只能单向通信,接收者只能被动的接收消息。
2)Binder:是Android系统内部使用的一种高效IPC机制,基于C/S架构,通过内存映射实现高效的进程间通信。高效性,数据传输速度快。支持复杂的数据类型传递
3)ContentProvider:是Android系统中一种轻量级的跨进程通信方式,主要用于在不同应用程序之间共享数据。
4)AIDL:是Android系统中用于定义跨进程通信接口的一种语言,它允许定义可在不同进程间共享的服务接口。

这里我们主要介绍Binder。

4.1 Binder


优点

解决安全问题,内存不够的问题。
1)比如加载图片的时候,出现崩溃,导致安全问题出现。如果用子线程进行加载,那么即使崩溃了也不影响主线程。在比如微信小程序就是另外进程,不能影响微信。
2)为什么手机运行内存8G,16G,加载一张大图就会导致内存不够用呢?难道他有几G那么大?并不是,因为每个app运行,根据手机的不同,进程可以分到几十兆,或者几百兆的内存空间(如下图)。所以多个进程,那么内存就多了。
在这里插入图片描述

内存划分

进程之间的内存是相互隔离的。
在这里插入图片描述
那么如何才能实现进程之间相互通讯?
Android 为什么要增加Binder?

在这里插入图片描述
传统的方式,需要进行两次拷贝。
在这里插入图片描述Binder拷贝:
在这里插入图片描述
内存映射到底是啥?虚拟地址映射到物理地址,而MMAP,就是将用户空间映射到内存空间。不需要拷贝了。通过快捷方式进行举例。

4.2 AIDL


是什么?简化调用Binder的流程。因为Binder的规则还是比较复杂的,而AIDL可以直接生成这套规则。这就是他的作用。

接下来我们就使用AIDL实现进程间通讯。比如说,两个进程,A进程通过发送一个字符串,B进程收到后进行对应的逻辑处理。

(1)打开aidl,不打开,生成不了aidl文件

先在build.gradle文件里面添加一个
android {...    buildFeatures.aidl = true...
}

(2)步骤 1: 定义AIDL接口

创建一个AIDL文件夹
在这里插入图片描述
创建AIDL文件
在这里插入图片描述

// IMessageService.aidl
package com.example.myapplicationa;// Declare any non-default types here with import statementsinterface IMessageService {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/String sendMessage(String message);
}

(3)步骤 2: 实现AIDL接口

在这里插入图片描述

package com.example.myapplicationaimport android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
import java.util.Localeclass MessageService : Service() {private val mBinder: IMessageService.Stub = object : IMessageService.Stub() {override fun sendMessage(message: String): String {// 这里可以添加一些处理逻辑,比如转换大小写等Log.d("AIDL A", "收到 sendMessage: ")return "Processed: " + message.uppercase(Locale.getDefault())}}override fun onBind(intent: Intent): IBinder? {return mBinder}
}

在AndroidManifest.xml中声明这个Service,并指定它运行在多进程中:

  <serviceandroid:name=".MessageService"android:exported="true"android:process=":remote"><intent-filter><action android:name="com.example.myapplicationa.IMessageService" /></intent-filter></service>

(4)步骤 3: 在App B中绑定Service

将IMessageService.aidl文件复制到App B的src/main/java/com/example/myapplicationa目录下。
在这里插入图片描述
在App B中创建一个ServiceConnection来绑定到App A的Service:

package com.example.myapplicationbimport android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import androidx.activity.ComponentActivity
import com.example.myapplicationa.IMessageServiceclass MainActivity : ComponentActivity() {private var mMessageService: IMessageService? = nullprivate var mIsBound = falseoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}private val mConnection: ServiceConnection = object : ServiceConnection {override fun onServiceConnected(className: ComponentName, service: IBinder) {mMessageService = IMessageService.Stub.asInterface(service)try {val response = mMessageService!!.sendMessage("Hello from App B")// 处理响应Log.d("AIDL B", "Received response: $response")} catch (e: RemoteException) {e.printStackTrace()}mIsBound = true}override fun onServiceDisconnected(arg0: ComponentName) {mMessageService = nullmIsBound = false}}override fun onStart() {super.onStart()val intent = Intent()intent.setComponent(ComponentName("com.example.myapplicationa", "com.example.myapplicationa.MessageService"))bindService(intent, mConnection, BIND_AUTO_CREATE)}override fun onStop() {super.onStop()if (mIsBound) {unbindService(mConnection)mIsBound = false}}
}

运行程序,如果收到这个log,就说明成功了。

在这里插入图片描述

好了,以上就是AIDL的简单使用。

五、多进程需要注意什么问题?


1、静态成员和单例模式完全失效 。Android 为每一个进程分配一个独立的虚拟机,不同虚拟机在内存分配上有不同地址空间,这就导致多进程下访问同一个类的对象会产生多分副本。所以在一个进程中修改某个值,只会在当前进程有效,对其他进程不会造成任何影响。

2、线程同步机制完全失效。因为多进程的内存地址空间不同,锁的不是同一个对象,所以不管是锁对象还是锁全局对象都无法保证线程同步。

3、SharedPreferences 的可靠性下降。因为SharedPreferences 底层通过读写XML实现,并发读写显然是不安全的操作,甚至会出现数据错乱。

4、Application 会多次创建。

5.1 Application 会多次创建 的解决方法


在Application的onCreate中获取进程Id来判断不同进程,然后做不同的事情。

public class MyApplication extends BaseApplication {public static MyApplication instances;@Overridepublic void onCreate() {super.onCreate();instances = this;if (isAppMainProcess()) {.....}.....}
}public static boolean isAppMainProcess() {try {int pid = android.os.Process.myPid();String process = getAppNameByPID(instances, pid);if (TextUtils.isEmpty(process)) {return true;} else if ("com.xxx.xxx".equalsIgnoreCase(process)) {return true;} else {return false;}} catch (Exception e) {e.printStackTrace();return true;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/399766.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Ajax使用说明】Ajax、Axios以及跨域

目录 一、原生Ajax 1.1 Ajax简介 1.2 XML简介 1.3 AJAX 的特点 1.3.1 AJAX的优点 1.3.2 AJAX 的缺点 1.4 AJAX 的使用 1.4.1AJAX的基本操作 1.4.2AJAX的传参 1.4.3 AJAX的post请求及设置请求体 1.4.4 AJAX响应json数据 1.4.5 AJAX请求超时与网络异常处理 1.4.5 AJ…

Ubuntu基础使用-适合新手的讲解

目录 一、基础操作 1. 终端重要热键 2. 基础命令 3. 通配符 二、文件与目录 1. 2.等价 3.帮助指令 4.当前路径 更改路径 5.创建与删除文件夹 6.创建与删除文件 7.重定向&#xff08;写入&#xff0c;追加写入&#xff09; 8.查看文件内容 9.wc指令 10.复制&…

Broken: Gallery靶机复现

靶机设置 靶机设置为NAT模式 靶机IP发现 nmap 192.168.112.0/24 靶机IP为192.168.112.142 目录扫描 dirsearch 192.168.112.142 访问浏览器 发现文件页面 查看后发现都没什么用 getshell hydra -L rockyou.txt -P rockyou.txt 192.168.112.142 ssh 尝试爆破ssh账号密码…

Agile Modbus移植教程--基于GD32F103C8T6+RT-Thread+mdk5

主机移植 0.下载源码 开源地址:GitHub - loogg/agile_modbus 1.复制源码 1.2、目录结构 名称说明doc文档examples例子参考示例figures素材inc头文件移植需要src源代码移植需要util提供简单实用的组件移植需要 本次移植需要的有 参考demo 头文件 源码 从机辅助文件 2.添…

基于lambda简化设计模式

写在文章开头 本文将演示基于函数式编程的理念&#xff0c;优化设计模式中繁琐的模板化编码开发&#xff0c;以保证用尽可能少的代码做尽可能多的事&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff…

数据结构+二叉遍历算法的应用

一、问题描述 编写一个程序&#xff0c;先用二叉树表示一个简单算术表达式&#xff0c;树的每一个 结点包括一个运算符或运算数。在简单算术表达式中只包含、-、 *、/和一位正整数且格式正确(不包含括号)&#xff0c;并且要按照先乘除后 加减的原则构造二叉树。如图 7.35 所示…

聚合平台项目优化(门面模式,适配器模式,注册器模式)

前言&#xff1a; 这篇文章的思路就是抛出问题&#xff0c;再思考解决方案&#xff0c;最后利用设计模式解决问题 项目背景&#xff1a; 聚合搜索平台的主要功能就是一个有强大搜索能力的一个项目 用户输入一个词&#xff0c;同时可以搜索出用户&#xff0c;文章和图片这种…

AI绘画: ComfyUI奥运高光时刻海报工作流,工作流拆解~

前言 点关注不迷路&#xff01; 这两天&#xff0c;阿里云的PAI ArtLab的ComfyUI新增了一个奥运高光时刻海报的工作流&#xff0c;小编测试下来&#xff0c;效果真的不错。不愧是大厂出品&#xff0c;必属精品。那么这次小编就简单梳理一下这个工作流的的各个部分&#xff0c…

基于vue框架的CKD电子病历系统nfa2e(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;患者,医生,药品信息,电子病历,临时医嘱,长期医嘱,健康科普 开题报告内容 基于Vue框架的CKD电子病历系统 开题报告 一、选题背景 随着信息技术的飞速发展和医疗信息化的深入推进&#xff0c;电子病历系统&#xff08;Electronic Medic…

分布式文件系统FastDFS入门

文章目录 一.分布式文件系统简介&#xff1a;二.FastDFS简介三.FastDFS组成Tracker ServerStorage Serverclient上传流程下载流程文件ID 四.FastDFS配置1.tracker.conf2.stroage 配置文件3.client配置文件 五.FastDFS使用六.代码实现通过execl调用客户端程序进行上传下载使用AP…

如何使用 Puppeteer 和 Node.JS 进行 Web 抓取?

什么是 Headlesschrome&#xff1f; Headless&#xff1f;是的&#xff0c;这意味着这个浏览器没有图形用户界面 (GUI)。不用鼠标或触摸设备与视觉元素交互&#xff0c;你需要使用命令行界面 (CLI) 来执行自动化操作。 Headlesschrome 和 Puppeteer 很多网页抓取工具都可适用…

成功解决7版本的数据库导入 8版本数据库脚本报错问题

我 | 在这里 ⭐ 全栈开发攻城狮、全网10W粉丝、2022博客之星后端领域Top1、专家博主。 &#x1f393;擅长 指导毕设 | 论文指导 | 系统开发 | 毕业答辩 | 系统讲解等。已指导60位同学顺利毕业 ✈️个人公众号&#xff1a;热爱技术的小郑。回复 Java全套视频教程 或 前端全套视频…

访问网站显示不安全打不开怎么办如何处理

当访问网站时浏览器提示“不安全”&#xff0c;这通常是由于多种原因造成的。下面是一些常见的原因及其解决办法&#xff1a; 未启用HTTPS协议 如果网站仅使用HTTP协议&#xff0c;数据传输没有加密&#xff0c;会被浏览器标记为“不安全”。解决办法是启用HTTPS协议&#xff…

一篇文章教会你如何使用Haproxy,内含大量实战案例

1. Haproxy 介绍 HAProxy是法国开发者 威利塔罗&#xff08;Willy Tarreau&#xff09; 使用C语言编写的自由及开放源代码软件&#xff0c;是一款具备高并发&#xff08;万级以上&#xff09;、高性能的TCP和HTTP应用程序代理. HAProxy运行在当前的硬件上&#xff0c;可以支持…

5款在线伪原创改写软件,智能改写文章效果好

在这个信息爆炸的时代&#xff0c;内容创作变得愈发重要&#xff0c;而对于创作者来说&#xff0c;有时需要一些得力的伪原创改写工具来辅助我们更好地改写出高质量的内容。今天我要和大家分享5款令人惊喜的在线伪原创改写软件&#xff0c;它们以出色的智能改写效果&#xff0c…

【Kubernetes】身份认证与鉴权

一&#xff0c;认证 所有 Kubernetes 集群有两类用户&#xff1a;由Kubernetes管理的ServiceAccounts(服务账户)和(Users Accounts)普通账户。 两种账户的区别&#xff1a; 普通帐户是针对(人)用户的&#xff0c;服务账户针对Pod进程普通帐户是全局性。在集群所有namespaces…

【Ai学习】一个技巧,解决99%Comfyui报错!

前言 comfyui以极高灵活度及节点化工作流&#xff0c;深受AI绘画者追捧&#xff0c;每当新的模型开源&#xff0c;comfyui都是最先进行适配。 comfyui高度兼容性及灵活性带来丰富强大的扩展&#xff08;插件&#xff09;生态&#xff0c;同时也带来一系列插件安装的问题&…

从今年的计算机视觉比赛看风向

记第一次参加CV比赛的经历-长三角&#xff08;芜湖&#xff09;人工智能视觉算法大赛-CSDN博客 去年参赛的记录里说了&#xff1a; 最近&#xff0c;同样的由芜湖举办的比赛又上线了&#xff0c;果然&#xff1a; 2023年是这些赛题&#xff0c;典型的CV&#xff1a; 今年变成…

阴阳脚数码管

1.小故事 最近&#xff0c;我接到了一个既“清肺”又“烧脑”的新任务&#xff0c;设计一个低功耗蓝牙肺活量计。在这个项目中我们借鉴了一款蓝牙跳绳的硬件设计方案&#xff0c;特别是它的显示方案——数码管。 在电子工程领域&#xff0c;初学者往往从操作LED开始&#xff…

【网络】IP的路径选择——路由控制

目录 路由控制表 默认路由 主机路由 本地环回地址 路由控制表的聚合 网络分层 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 路由控制表 在数据通信中&#xff0c;IP地址作为网络层的标识&#xff0c;用于指定数据包的目标位置。然而&#xff0c;仅有IP地址并不足以确…