4

I planned to use shared memory between an activity and a service in separate process to transfer big content between them.

To that end I read every info I have found on MemoryFile and how to transfer it between activity and specifically this stackoverflow entry what is the use of MemoryFile in android .

But I am unable to call getParcelFileDescriptor (using the described solution) on my android version 4.xx. It seems that the method does not exist anymore.

Nevertheless I come to the following code to send a ParcelFileDescriptor to my service (take it as pseudo code, but in fact it is ruboto code):

shm = MemoryFile.new("picture", 1000)
f = shm.getFileDescriptor() 
p = ParcelFileDescriptor.dup( f)

b = Bundle.new()
b.putParcelable( "shm", p)
msg.setData( b)
service.send( msg)

To test that the shared memory is properly accessible, I have written a string in it, and try to retrieve it on the service side.

I have the following (true java) code to do that:

 Parcelable p = msg.getData().getParcelable("shm");
 ParcelFileDescriptor shm = (ParcelFileDescriptor) p;
 FileDescriptor f = shm.getFileDescriptor();

 if( f.valid()) {
     FileInputStream in = new FileInputStream( f);
     String s = readString( in); // this fail!
}

Every thing is ok, f is valid but I cannot read from the received fileDiscriptor, I get: java.io.IOException: read failed: EINVAL (Invalid argument)

The code for the reading is the following:

public String readString(InputStream inputStream) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String s = r.readLine();
return s;
}

So two question:

  • I am doing wrong ? (in any of the side)
  • or does the MemoryFile amputed from #getParcelFileDescriptor is now unusable as a mean to share memory betweens two process ?

In this latter case, I fail to see any interest in this class then...

I have seen other article mentioning JNI code to used shared memory but would like to avoid that additional complexity.

Community
  • 1
  • 1
yves
  • 664
  • 1
  • 12
  • 24

1 Answers1

0

I managed to transfer data between applications through a MemoryFile on Android 4.0.4 using shm.getFileDescriptor() and ParcelFileDescriptor.dup(f) so, fortunately, this class is still usable. In your case the problem may be in the content of the file, although I don't know how it can cause an Invalid argument error. Try writing and reading a fixed-length byte array instead of a string (which you don't actually write in the provided code) and read it simply with InputStream.read(buffer).

lapis
  • 6,872
  • 4
  • 35
  • 40
  • Although, for me it worked only for the first read/write, after that the remote side couldn't read anything and after a GC pass the file descriptor became invalid. Seems like you must use mmap and other native functions in order to make it work properly, so I ended up using LocalSocket for my task instead of MemoryFile. – lapis Dec 23 '13 at 22:09