Ответ 1
Похоже, причиной было ParcelFileDescriptor
, являющийся аргументом метода службы. Если служба возвращает ParcelFileDescriptor
, она работает должным образом.
Служба отправки (процесс A)
public sendInputStream() {
InputStream is = ...; // that the stream for process/service B
ParcelFileDescriptor pfd = inputStreamService.inputStream();
OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(pfd);
int len;
byte[] buf = new byte[1024];
try {
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
} catch (IOException e) {
} finally {
try { is.close(); } catch (IOException e1) {}
try { os.close(); ] catch (IOException e1) {}
}
}
Код услуги приема (процесс B)
Служба приема .aidl
:
package org.exmaple;
interface IInputStreamService {
ParcelFileDescriptor inputStream();
}
Служба приема, вызываемая процессом A:
public class InputStreamService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IInputStreamService.Stub mBinder = new IInputStreamService.Stub() {
@Override
public void ParcelFileDescriptor inputStream() throws RemoteException {
// one can read the contents of the Processes A InputStream
// from the following OutputStream
OutputStream os = ...;
ParcelFileDescriptor pfd = ParcelFileDescriptorUtil.pipeTo(os);
return pfd;
}
};
ParcelFileDescriptorUtil - это вспомогательный класс, с классическим потоком копирования java.io.
stream-to-stream. Теперь мы должны использовать метод pipeTo()
.
public class ParcelFileDescriptorUtil {
public static ParcelFileDescriptor pipeTo(OutputStream outputStream) throws IOException {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor readSide = pipe[0];
ParcelFileDescriptor writeSide = pipe[1];
// start the transfer thread
new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream).start();
return writeSide;
}
static class TransferThread extends Thread {
final InputStream mIn;
final OutputStream mOut;
TransferThread(InputStream in, OutputStream out) {
super("ParcelFileDescriptor Transfer Thread");
mIn = in;
mOut = out;
setDaemon(true);
}
@Override
public void run() {
byte[] buf = new byte[1024];
int len;
try {
while ((len = mIn.read(buf)) > 0) {
mOut.write(buf, 0, len);
}
mOut.flush(); // just to be safe
} catch (IOException e) {
LOG.e("TransferThread", e);
}
finally {
try {
mIn.close();
} catch (IOException e) {
}
try {
mOut.close();
} catch (IOException e) {
}
}
}
}
}
Это позволяет вам передавать InputStreams через границы процесса, один из недостатков заключается в том, что в копиях потокового потока присутствует некоторое время процессора.