当前位置: 首页 > news >正文

Android MemoryFile 共享内存

应用场景:

跨进程传输大数据,如文件、图片等;

技术选型:

共享内存–MemoryFile;

优点:

1. 共享内存没有传输大小限制,所以和应用总的分配内存一样(512MB);
2. MemoryFile 是对 SharedMemory 的包装,使用简单便于管理;

实现步骤:

(以A进程共享文件a.txt给B进程为例)

A进程: 创建共享内存空间工具类
 
public class ShareMemoryUtils {private static ParcelFileDescriptor getPfdFromMemoryFile(final String name, final byte[] bytes) {ParcelFileDescriptor pfd = null;try {long startTime = System.currentTimeMillis();MemoryFile memoryFile = null;try {memoryFile = new MemoryFile(name, bytes.length);memoryFile.allowPurging(true);memoryFile.writeBytes(bytes, 0, 0, bytes.length);pfd = getParcelFileDescriptor(memoryFile);} catch (Exception e) {e.printStackTrace();} finally {closeMemoryFile(memoryFile, null);}}});}return pfd;}private static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile memoryFile) {try {Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");method.setAccessible(true);FileDescriptor fd = (FileDescriptor) method.invoke(memoryFile);return ParcelFileDescriptor.dup(fd);} catch (Exception e) {e.printStackTrace();return null;}}private static void closeMemoryFile(MemoryFile memoryFile, ParcelFileDescriptor pfd) {if (pfd != null) {try {pfd.close();} catch (IOException e) {e.printStackTrace();}}if (memoryFile != null) {memoryFile.close();}}}
A进程:创建aidl接口,使用binder接口传递文件描述符
interface IMemoryFileApi {ParcelFileDescriptor getParcelFileDescriptor(String type, String params);boolean setParcelFileDescriptor(String type, in ParcelFileDescriptor pfd, String params);oneway void releaseParcelFileDescriptor(String type);
}
B进程:通过bindService连接到A进程,并调用aidl接口获取文件描述符
/*** 通过 binder 接口获取远程进程共享内存的文件描述符*/private ParcelFileDescriptor getParcelFileDescriptor() {try {if (iMemoryFileApi != null) {ParcelFileDescriptor pfd = iMemoryFileApi.getParcelFileDescriptor();return pfd;}} catch (Exception e) {e.printStackTrace();}return null;}
B进程:通过文件描述符读取数据流即可;

注意:

文件描述符在每个进程都有副本,A进程的文件描述符被B进程接收后,实际上已经有了两份文件描述符,即两个进程有各自的内存映射空间。所以B进程读取数据流之后,除了要关闭自己进程的文件描述符对象之外,还要调用接口关闭A进程中的文件描述符;
B进程想要把修改后的文件数据回写给A进程时,需要做的操作和A进程的操作是完全一样的,把文件数据重新创建共享内存,再把文件描述符通过binder接口传递给A进程即可;

总结

网上很多时间比较久的贴子,通过各种反射在A进程获取MemoryFIle来读取共享数据,这种方式并不可取;MemoryFile新版本的封装方式就体现了它的使用方式,Google是希望随时使用随时创建MemoryFile并把文件描述附共享出去这种方式来实现功能的。


android MemoryFile内存共享

进程之间传递数据,由于Binder传递数据有限制1M,所以如果遇到大的数据传递的时候就需要使用使用到MemoryFile内存共享来解决,最合适不过了

首先,MemoryFile是基于Binder自带的transact方法进行传输数据的,因此直接继承Binder即可,不过一般项目中免不了传递一些基本数据类型或者bean数据,因此一般结合aidl一起使用。

android aidl使用记录

  • 服务端处理数据
private byte[] buffer = new byte[1024];//public class MyBinder extends IRtcService.Stub {public class MyBinder extends Binder {//此方法Binder自带@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {LogUtil.e("接收到远端调用" + "code" + code);if (code == 100) {try {ParcelFileDescriptor pfd = data.readParcelable(null);// 或者
//                    ParcelFileDescriptor pfd = data.readFileDescriptor();FileDescriptor fileDescriptor = pfd.getFileDescriptor();FileInputStream fi = new FileInputStream(fileDescriptor);fi.read(buffer);fi.close();LogUtil.e("--->" + new String(buffer).replace("\0", ""));//返回给客户端reply.writeString("服务器接受数据成功");reply.writeInt(200);return true;} catch (IOException e) {e.printStackTrace();}}return super.onTransact(code, data, reply, flags);}}
  • 客户端
private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {try {/****/// 参数1文件名,可为null,参数2文件长度mMemoryFile = new MemoryFile(null, 1024);//在设置了allowPurging为false之后,这个MemoryFile对应的Ashmem就会被标记成"pin",// 那么即使在android系统内存不足的时候,也不会对这段内存进行回收mMemoryFile.allowPurging(false);android.os.Parcel data = android.os.Parcel.obtain();android.os.Parcel reply = android.os.Parcel.obtain();byte[] buffer = "31283216382163812362183621832163812".getBytes();mMemoryFile.writeBytes(buffer, 0, 0, buffer.length);Method getFileDescriptorMethod = mMemoryFile.getClass().getDeclaredMethod("getFileDescriptor");if (getFileDescriptorMethod != null) {FileDescriptor fileDescriptor = (FileDescriptor) getFileDescriptorMethod.invoke(mMemoryFile);// 序列化,才可传送ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fileDescriptor);//写入数据,对应服务端用data.readParcelable(null)接收数据data.writeParcelable(pfd, 0);// 或者,对应服务端用data.readFileDescriptor()接收数据
//                    data.writeFileDescriptor(fileDescriptor);/*** code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法;* data客户端传递过来的参数;* replay服务器返回回去的值;* flags标明是否有返回值,0为有(双向),1为没有(单向)。*/service.transact(100, data, reply, 0);//服务器返回的值String message = reply.readString();LogUtil.e("--message--->" + message);int code = reply.readInt();LogUtil.e("--code--->" + code);if (code==200){data.recycle();reply.recycle();mMemoryFile.close();mMemoryFile=null;}}} catch (RemoteException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {if (mConnection != null) {try {iRtcService = null;unbindService(mConnection);} catch (Exception e) {}}}};
  • 结果

    客户端

03-15 21:16:36.011 4327-4327/com.fuyao.elf_android_remote E/elf_remote: --message--->服务器接受数据成功
03-15 21:16:36.011 4327-4327/com.fuyao.elf_android_remote E/elf_remote: --code--->200

 服务端

03-15 21:16:36.010 4300-4313/com.fuyao.elf_android_center:rtc_remote E/elf_center: 接收到远端调用code100
03-15 21:16:36.010 4300-4313/com.fuyao.elf_android_center:rtc_remote E/elf_center: --->31283216382163812362183621832163812

Android内存映射文件实现

1. 什么是内存映射文件

内存映射文件是一种将磁盘上的文件映射到内存中的方法。通过内存映射文件,可以将文件的内容直接映射到内存中的一个地址空间,从而可以直接对内存进行读写操作,而无需通过传统的文件IO操作。

在Android开发中,内存映射文件常常用于处理大文件或者需要频繁读写的文件,因为通过内存映射文件可以获得更高的IO性能。

2. Android内存映射文件的实现方式

Android提供了MemoryFile类来实现内存映射文件的功能。MemoryFile是一个基于共享内存的IPC(进程间通信)机制,它允许一个进程将一个内存映射文件映射到另一个进程的地址空间中。

下面是一个简单的代码示例,演示了如何使用MemoryFile实现内存映射文件:

// 创建一个内存映射文件
MemoryFile memoryFile = new MemoryFile("test", 1024);// 向内存映射文件写入数据
String data = "Hello, MemoryFile!";
byte[] buffer = data.getBytes();
memoryFile.writeBytes(buffer, 0, 0, buffer.length);// 从内存映射文件读取数据
byte[] readBuffer = new byte[buffer.length];
memoryFile.readBytes(readBuffer, 0, 0, readBuffer.length);
String readData = new String(readBuffer);// 打印读取的数据
System.out.println(readData);// 释放内存映射文件
memoryFile.close();


在上面的代码中,首先我们创建了一个大小为1024字节的内存映射文件。然后,我们向内存映射文件写入了字符串数据,接着又从内存映射文件中读取了数据,并将其转换为字符串。最后,我们释放了内存映射文件。

需要注意的是,MemoryFile类只能在同一个进程的不同线程之间进行通信,如果需要在不同进程之间通信,则需要使用其他的IPC机制,比如Binder。

3. 内存映射文件的优势和应用场景


内存映射文件相比于传统的文件IO操作有如下优势:

  • 更高的IO性能:由于内存映射文件将文件内容映射到内存中,所以可以避免频繁的磁盘IO操作,从而获得更高的IO性能。
  • 更低的内存占用:内存映射文件只将文件的部分或全部内容映射到内存中,而不是将整个文件加载到内存中,所以可以减少内存的占用。
  • 更方便的数据访问:通过内存映射文件,可以直接对内存中的数据进行读写操作,而无需通过文件IO相关的API,从而简化了数据访问的操作。

内存映射文件常常应用于以下场景:

  • 大文件处理:当需要处理大文件时,通过内存映射文件可以获得更高的IO性能。
  • 频繁读写文件:当需要频繁读写文件时,通过内存映射文件可以避免频繁的磁盘IO操作,提高程序的响应速度。
  • 进程间通信:通过内存映射文件可以在同一个进程的不同线程之间进行通信。

4. 总结

本文介绍了Android内存映射文件的实现方式以及其优势和应用场景。通过内存映射文件,我们可以获得更高的IO性能和更方便的数据访问方式。在处理大文件或者需要频繁读写文件的场景下,使用内存映射文件可以提高程序的性能和响应速度。
 

相关文章:

Android MemoryFile 共享内存

应用场景: 跨进程传输大数据,如文件、图片等; 技术选型: 共享内存–MemoryFile; 优点: 1. 共享内存没有传输大小限制,所以和应用总的分配内存一样(512MB)&#xff1…...

【lua】记录函数名和参数(为了延后执行)

需求背景 一个服务缓存玩家信息到对象里,通过对象的函数定时同步到数据库中,如果玩家掉线 清空对象,但是后续步骤导致对象数据需要变更,对象不存在, 就不方便变更了,怎么处理? 方案思考 1.临…...

2023.11.22 数据仓库2-维度建模

目录 1.数仓建设方案 2.数仓结构图,项目架构图 2.1项目架构图 2.2数仓结构图 3.建模设计 4.维度建模 什么是事实表: 什么是维度表: 数据发展模式y以及对应的模型 5.数仓建设规范 数据库划分规范 表命名规范 表字段类型规范 1.数仓建设方案 ODS: 源数据层(临时存储层) 贴…...

pycharm 创建的django目录和命令行创建的django再使用pycharm打开的目录对比截图 及相关

pytcharm创建django的项目 命令行创建的django 命令行创建项目时 不带路径时 (.venv) D:\gbCode>django-admin startproject gbCode 命令行创建项目时 带路径时 -- 所以如果有目录就指定路径好 (.venv) D:\gbCode>django-admin startproject gbCode d:\gbCode\...

【Pytorch】Visualization of Fature Maps(2)

学习参考来自 使用CNN在MNIST上实现简单的攻击样本https://github.com/wmn7/ML_Practice/blob/master/2019_06_03/CNN_MNIST%E5%8F%AF%E8%A7%86%E5%8C%96.ipynb 文章目录 在 MNIST 上实现简单的攻击样本1 训练一个数字分类网络2 控制输出的概率, 看输入是什么3 让正确的图片分…...

【目标检测】保姆级别教程从零开始实现基于Yolov8的一次性筷子计数

前言 一,环境配置 一,虚拟环境创建 二,安装资源包 前言 最近事情比较少,无意间刷到群聊里分享的基于百度飞浆平台的一次性筷子检测,感觉很有意思,恰巧自己最近在学习Yolov8,于是看看能不能复…...

笔记:内网渗透流程之信息收集

信息收集 首先,收集目标内网的信息,包括子网结构、域名信息、IP地址范围、开放的端口和服务等。这包括通过主动扫描和渗透测试工具收集信息,以及利用公开的信息源进行信息搜集。 本机信息收集 查看系统配置信息 查看系统详细信息&#xf…...

【2023.11.23】JDBC基本连接语法学习➹

1.导入jar包依赖:mysql-connector-java-8.0.27.jar 2.连接数据库! 3.无法解析类->导入java.sql.*,(将项目方言改为Mysql) JDBC,启动!! public class Main {public static voi…...

ubuntu 安装python3.13

列出 /usr/bin/ 目录下所有以 python 开头的文件和目录 ls /usr/bin/python* 添加Python软件源。您可以通过以下命令将Python的软件源添加到您的系统中 sudo add-apt-repository ppa:deadsnakes/ppa 然后运行以下命令以更新软件包列表: sudo apt-get update 安…...

OpenCV数据类型及CV_16UC1深度图ros订阅

最近用到深度图,对其数据类型及显示有些迷惑,记笔记于此: 目录 一、cv::Mat 的数据类型及转换方式1. cv::Mat 数据类型2. cv::Mat 数据类型互转2.1 OpenCV数据类型转换的函数2.2 可视化深度图像(CV_16UC1)二、cv::Mat 与 sensor_msgs::msg::Image 互转(基于cv_bridge)1.…...

华清远见嵌入式学习——网络编程——小项目

项目要求&#xff1a; 代码实现&#xff1a; 服务器端&#xff1a; #include <myhead.h>//定义协议包 struct proto {char type;char name[20];char text[128]; };int main(int argc, const char *argv[]) {//判断从终端输入的字符串的个数if(argc ! 3){printf("…...

分库分表、分布式数据库、MPP

分库分表、分布式数据库、MPP的区别吗&#xff1f; 一、MySQL分库分表和MySQL分布式集群在性能方面各有优劣&#xff0c;具体取决于应用场景和需求。 MySQL分库分表&#xff1a; 在分库分表的场景下&#xff0c;可以将负载分散到多个数据库实例上&#xff0c;从而提高整体性能…...

浅学指针(2)数组函数传值调用

系列文章目录 文章目录 系列文章目录前言1. 指针的使⽤和传址调⽤结论&#xff1a;实参传递给形参的时候&#xff0c;形参会单独创建⼀份临时空间来接收实参&#xff0c;对形参的修改不影响实 参。那么这个时候&#xff0c;就要搬出指针大哥&#xff0c;在main函数中将a和b的地…...

C++之unordered_map/set的使用

前面我们已经学习了STL中底层为红黑树结构的一系列关联式容器——set/multiset 和 map/multimap(C98). unordered系列关联式容器 在C98中, STL提供了底层为红黑树结构的一系列关联式容器, 在查询时效率可达到log2N,即最差情况下需要比较红黑树的高度次, 当树中的节点非常多时,…...

docker打包chatpdf(自写)

docker打包上传 docker build -t kitelff/chatpdf:v0.1 .##修改镜像名字 docker tag c2c1a0eb4e08 kitelff/chatpdf:v0.1## push docker push kitelff/chatpdf:v0.1上传文件&#xff0c;测试效果...

shell基础

一.Shell脚本编程概述 1.基本概念 将要执行的命令按顺序保存到一个文本文件&#xff1b; 给该文件可执行权限&#xff1b; 可结合各种Shell控制语句以完成更复杂的操作。 2.作用 Linux系统中的Shell是一个特殊的应用程序&#xff0c;它介于操作系统内核与用户之间&#x…...

力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)

Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff…...

使用正则表达式来判断一个字符串只是否包含数字

使用正则表达式来判断一个字符串只是否包含数字 1、第一种 import java.util.regex.Pattern;public class Main {public static void main(String[] args) {String inputString "12345";if (containsOnlyDigits(inputString)) {System.out.println("字符串只…...

C#Wpf关于日志的相关功能扩展

目录 一、日志Sink(接收器) 二、Trace追踪实现日志 三、日志滚动 一、日志Sink(接收器) 安装NuGet包&#xff1a;Serilog Sink有很多种&#xff0c;这里介绍两种&#xff1a; Console接收器&#xff08;安装Serilog.Sinks.Console&#xff09;; File接收器&#xff08;安装…...

亚马逊云科技AI创新应用下的托管在AWS上的数据可视化工具—— Amazon QuickSight

目录 Amazon QuickSight简介 Amazon QuickSight的独特之处 Amazon QuickSight注册 Amazon QuickSight使用 Redshift和Amazon QuickSightt平台构建数据可视化应用程序 构建数据仓库 数据可视化 Amazon QuickSight简介 亚马逊QuickSight是一项可用于交付的云级商业智能 (BI…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...