这一节了解一下共享内存,Android系统实现了一个匿名共享内存,用来在应用程序之间共享数据。匿名共享内存与传统的Linux系统实现的共享内存一样,都是基于内核提供的临时文件系统tmpfs实现的。但是前者对内存块进行了更为精细化的管理。应用程序可以动态地将一块匿名共享内存划分为若干个小块,当这些小块内存不再需要使用时,它们就可以被内存管理系统回收。匿名共享内存系统是以Ashmem驱动程序为基础的,系统中所有的匿名共享内存都由Ashmem驱动程序负责分配和管理。 在应用程序框架层中,是通过一个Java类MemoryFile来使用匿名共享内存;
MemoryFile
MemoryFile是对SharedMemory的包装,官方推荐使用SharedMemory
SharedMemory
SharedMemory只能经过调用SharedMemory.create静态方法或者经过Parcel反序列化的方式进行建立。函数由于SharedMemory类实现了Parcelable,因此能够经过binder跨进程传输。
简单看个栗子:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.MemoryFile;
import android.os.Parcel;
import android.os.RemoteException;
import androidx.appcompat.app.AppCompatActivity;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
String str = "来自发送端的数据";
MemoryFile memoryFile = new MemoryFile("Asheme", str.getBytes().length);
memoryFile.writeBytes(str.getBytes(), 0, 0, str.getBytes().length);
Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
FileDescriptor des = (FileDescriptor) method.invoke(memoryFile);
Parcel data = Parcel.obtain();
data.writeFileDescriptor(des);
data.writeInt(str.getBytes().length);
Parcel reply = Parcel.obtain();
service.transact(12345, data, reply, 0);
} catch (RemoteException | IOException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, AshmemService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
import static java.nio.charset.StandardCharsets.UTF_8;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class AshmemService extends Service {
public AshmemService() {
}
@Override
public IBinder onBind(Intent intent) {
return new AshmemBinder();
}
class AshmemBinder extends Binder {
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (code == 12345) {
try {
ParcelFileDescriptor pfd = data.readFileDescriptor();
int size = data.readInt();
InputStream inputStream = new FileInputStream(pfd.getFileDescriptor());
byte[] bytes = new byte[1024];
inputStream.read(bytes, 0, size);
String message = new String(bytes, 0, size, UTF_8);
Log.i("LJT", "接受到的数据为:" + message);
} catch (IOException e) {
e.printStackTrace();
}
return true;
} else {
return super.onTransact(code, data, reply, flags);
}
}
}
}
输出:
接受到的数据为:来自发送端的数据