Android系统的IPC方式通常为:文件、socket、binder、messenger、AIDL、ContentProvider,此外还有个Anonymous Shared Memory(匿名共享内存),这篇文章介绍Ashm基础使用相关知识。
Android api27加入了SharedMemory类,27之前需要通过反射去拿到文件描述符。
demo为MainActivity和一个远程服务(指定了process的service)之间的通信,步骤如下:
1、创建aidl文件IMemoryAidlInterface
interface IMemoryAidlInterface {
ParcelFileDescriptor getParcelFileDescriptor();
}
1、创建一个服务并在manifest文件中指定process
<service android:name=".MemoryFetchService"
android:process=":ashm"/>
在服务MemoryFetchService中创建共享内存虚拟文件并设置size,写入内容为一个数组。
public class MemoryFetchService extends Service {
private static final String TAG = "MemoryFetchService";
private static final String SHM_FILE_NAME = "test_memory";
@Override
public IBinder onBind(Intent intent) {
return new MemoryFetchStub();
}
static class MemoryFetchStub extends IMemoryAidlInterface.Stub {
@Override
public ParcelFileDescriptor getParcelFileDescriptor() throws RemoteException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
MemoryFile memoryFile = null;
try {
memoryFile = new MemoryFile(SHM_FILE_NAME, 1024);
memoryFile.getOutputStream().write(new byte[]{1, 2, 3, 4, 5});
Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
FileDescriptor des = (FileDescriptor) method.invoke(memoryFile);
return ParcelFileDescriptor.dup(des);
} catch (Exception e) {
Log.d(TAG, "getParcelFileDescriptor: exception : " + e.toString());
}
}else {
//TODO use SharedMemory to get fd
}
return null;
}
}
}
在MainActivity中绑定服务,读取共享内存文件中的内容:
private void bind() {
Intent intent = new Intent(MainActivity.this, MemoryFetchService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
byte[] content = new byte[10];
IMemoryAidlInterface iMemoryAidlInterface
= IMemoryAidlInterface.Stub.asInterface(service);
try {
ParcelFileDescriptor parcelFileDescriptor
= iMemoryAidlInterface.getParcelFileDescriptor();
FileDescriptor descriptor = parcelFileDescriptor.getFileDescriptor();
FileInputStream fileInputStream = new FileInputStream(descriptor);
int read = fileInputStream.read(content);
Log.d(TAG, "onServiceConnected: read == " + read);
} catch (Exception e) {
Log.d(TAG, "onServiceConnected: exception: " + e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Service.BIND_AUTO_CREATE);
}
debug可以看到content中的内容即为在MemoryFetchService中写入的内容。
adb shell进入设备后,通过lsof|grep "test_memory"可以查看到创建的匿名共享内存虚拟文件:
130|Galileo:/ # lsof |grep "test_memory"
com.***.ash 27421 u0_a73 mem unknown
到这里Android匿名共享内存简单使用demo已经完了,代码在这里clone。