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性能和更方便的數據訪問方式。在處理大文件或者需要頻繁讀寫文件的場景下,使用內存映射文件可以提高程序的性能和響應速度。
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164739.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164739.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164739.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 根據文件名獲取文件類型

比如文件名是“測試文件.png”,則獲取的文件類型就是 png 直接上一個通用的方法,拿去直接就能用。 // 比如入參文件名是“測試文件.png”,則出參就是 pngprivate String getFileSuffix(String fileName) {String[] fileStr fileName.split(&…

educoder中共享單車之數據可視化

第1關:繪制地圖 <%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> <html> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&…

專用設備上的SD卡插入電腦想讀取數據,提示要格式化?

環境&#xff1a; Win10 專業版 車載感應數據專用SD卡 問題描述&#xff1a; 專用設備上的SD&#xff0c;現在把SD卡從設備取出&#xff0c;用讀卡器插入電腦提示要格式化&#xff1f; 解決方案&#xff1a; 1.先進入PE查看SD分區情況&#xff0c;SD格式為ext4 查看文件…

lombok中使用@Builder構造器模式時的默認值問題

這里寫自定義目錄標題 問題case原因解決方案 文章參考來源&#xff1a;https://chenyongjun.vip/articles/107 問題case Lombok 使用廣泛&#xff0c;這里分享一個 Lombok Builder 小 case&#xff0c;今天自己踩了坑。 Data Builder public class User {private String name…

MLP 有哪些可學習的參數

多層感知機&#xff08;MLP&#xff09;的參數是需要在訓練過程中學習的。MLP是一種前饋神經網絡&#xff0c;其結構包括輸入層、多個隱藏層和輸出層。在訓練過程中&#xff0c;MLP通過反向傳播算法來調整網絡的權重&#xff0c;以最小化預測值與實際值之間的誤差。 MLP的學習…

安卓開發——Android Studio常見報錯與解決方法

1. No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-android 這個錯誤是由于較新版本的NDK的./toolchains目錄中沒有arm-linux-androideabi文件&#xff0c;解決辦法是從舊的NDK版本里面復制到自己的NDK的版本里面&#xff0c;就可以了。 打…

WSL登錄時提示nsenter: cannot open /proc/320/ns/time: No such file or directory的解決辦法

在登錄 WSL 的 Ubuntu 時&#xff0c;不僅要求 root 權限&#xff0c;還登錄失敗&#xff0c;提示“nsenter: cannot open /proc/320/ns/time: No such file or directory”。 解決辦法是在 powershell 中執行 “wsl – sudo vi /etc/profile”命令&#xff0c;刪除文件內容&a…

JavaWeb——感謝尚硅谷官方文檔

JavaWeb——感謝尚硅谷官方文檔 XML一、xml簡介二、xml的語法1、文檔申明2、xml注釋3、xml元素4、xml屬性5、xml語法規則 三、xml解析技術1、使用dom4j解析xml Tomcat一、JavaWeb的概念二、web資源的分類三、常見的web服務器四、Tomcat的使用1、安裝2、Tomcat的目錄介紹3 啟動T…

初識Java 18-3 泛型

目錄 邊界 通配符 編譯器的能力范疇 逆變性 無界通配符 捕獲轉換 本筆記參考自&#xff1a; 《On Java 中文版》 邊界 在泛型中&#xff0c;邊界的作用是&#xff1a;在參數類型上增加限制。這么做可以強制執行應用泛型的類型規則&#xff0c;但還有一個更重要的潛在效果…

如何在AD的PCB板做矩形槽孔以及如何倒圓弧角

Altium Designer 22下載安裝教程-CSDN博客 如何在AD上創建完整的項目-CSDN博客 開始前&#xff0c;請先安裝后AD&#xff0c;并創建好項目。 目錄 1. 如何在AD的PCB板做矩形槽孔 2. 如何在AD的PCB板倒圓弧角 1. 如何在AD的PCB板做矩形槽孔 首先&#xff0c;我們進入上面創…

PTA 7-9 堆棧操作合法性

7-9 堆棧操作合法性 分數 20 全屏瀏覽題目 作者 DS課程組 單位 浙江大學 假設以S和X分別表示入棧和出棧操作。如果根據一個僅由S和X構成的序列&#xff0c;對一個空堆棧進行操作&#xff0c;相應操作均可行&#xff08;如沒有出現刪除時棧空&#xff09;且最后狀態也是棧空…

2023年11個最佳免費WordPress主題

如果您剛剛開始使用 WordPress&#xff0c;您可能會很自然地認為&#xff0c;只要免費的WordPress主題看起來像您想要的網站主題&#xff0c;那么它就很合適。不幸的是&#xff0c;事情并沒有那么簡單。這就是為什么在今天的文章中&#xff0c;我們概述了一份可靠的標準清單&am…

某基金公司趙哥“逆襲”了!!!

趙哥&#xff0c;在上海一家基金公司做運維主管。 平時工作的首要任務&#xff0c;就是保障公司各項信息系統的安全運行。 萬一系統運行中出現了一些重要問題&#xff0c;他還要負責進行調查、記錄與匯報... 總之&#xff0c;責任很重&#xff0c;該說不說&#xff0c;搞不好…

Java互聯網+公立醫院績效考核源碼

一、建設信息化醫院績效考核的意義 1.提高考核效率&#xff1a;通過信息化手段&#xff0c;可以將績效考核數據自動采集、整理、分析和報告&#xff0c;大大提高了考核效率&#xff0c;減少了人工干預和錯誤率。 2.增強考核公正性&#xff1a;信息化考核可以減少人為因素的干…

Electronica上海 Samtec 驗證演示 | FireFly?Micro Flyover System?

摘要/前言 在圓滿結束的2023慕尼黑上海電子展上&#xff0c;Samtec虎家團隊為觀眾帶來了前所未有的豐富體驗&#xff1a;產品展示、采訪、Demo演示、抽獎互動~ 尤其是Demo演示&#xff0c;虎家工程師FAE Marcus為大家帶來了數個精彩的產品與系統講解演示。其中更不乏合作伙伴…

Windows、VMware問題集合

Windows、VMware問題集合 一. Windows11安裝VMware17提升虛擬機性能1. 桌面右擊圖標點擊屬性——>兼容性&#xff0c;找到“以管理員身份運行此程序”勾選&#xff0c;最后點擊確定即可。2. 關閉win11的內核隔離功能。 二. VMware虛擬機報錯&#xff08;虛擬化性能計數器需要…

C語言——求分段函數 y=f(x)的值

求分段函數 yf(x)的值,f(x)的表達式如下: #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int x,y;printf("請輸入x的值&#xff1a;");scanf("%d",&x);if(x>5){yx3;}else if(x>0 && x<5){y0;}elsey2*x30;pr…

Python 基礎【四】--數據類型-字符串【2023.11.23】

1 .定義 字符串是 Python 的一種數據類型&#xff0c;它可以通過單引號 ‘、雙引號 "、三引號 ‘’’ 或 “”"來定義。 aabcd bacsdcd c"""accsfv""" print(a) print(b) print(c)2 .基本操作 訪問單個字符 注意&#xff1a;從0開始…

Java_注解

1. 簡介 在Java中&#xff0c;注解&#xff08;Annotation&#xff09;是一種元數據形式&#xff0c;它為代碼添加了額外的信息&#xff0c;這些信息可以被編譯器、工具、框架或運行時環境使用。注解提供了一種聲明性的方式來向程序中添加元數據&#xff0c;而不需要修改程序的…

Harmony Ble藍牙App(二)連接與發現服務

Ble藍牙App&#xff08;二&#xff09;連接與發現服務 前言正文一、BlePeripheral回調二、連接和斷連三、連接狀態回調四、發現服務五、服務提供者六、顯示服務七、源碼 前言 在上一篇中我們進行掃描設備的處理&#xff0c;本文中進行連接和發現服務的數據處理&#xff0c;運行…