ある Android サービスから別のプロセス内で実行されている別のサービスに InputStream を「送信」しParcelFileDescriptor.createPipe()
たいBinder IPC を使用。
コードの送信 (プロセス A)
特定の InputStream を受信側サービスに送信したい:
public sendInputStream() {
InputStream is = ...; // that's the stream for process/service B
ParcelFileDescriptor pdf = ParcelFileDescriptorUtil.pipeFrom(is);
inputStreamService.inputStream(pdf);
}
ParcelFileDescriptorUtil はヘルパー クラスであり、従来java.io.
のストリームからストリームへのコピー Thread:
public class ParcelFileDescriptorUtil {
public static ParcelFileDescriptor pipeFrom(InputStream inputStream) throws IOException {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor readSide = pipe[0];
ParcelFileDescriptor writeSide = pipe[1];
// start the transfer thread
new TransferThread(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide)).start();
return readSide;
}
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) {
}
}
}
}
}
サービスコードの受け取り(プロセスB)
受信サービスの.aidl
:
package org.exmaple;
interface IInputStreamService {
void inputStream(in ParcelFileDescriptor pfd);
}
プロセス 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 inputStream(ParcelFileDescriptor pfd) throws RemoteException {
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
OutputStream os = ...;
int len;
byte[] buf = new byte[1024];
try {
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
} catch (IOException e) {
// this catches the exception shown below
}
}
};
しかしin.read()
、inputStream()
常にスローされますIOException
java.io.IOException: read failed: EBADF (Bad file number)
at libcore.io.IoBridge.read(IoBridge.java:442)
at java.io.FileInputStream.read(FileInputStream.java:179)
at java.io.InputStream.read(InputStream.java:163)
read()
ファイル記述子が閉じられると、EBADF errno が設定されるようです。しかし、何が原因で、どのように修正すればよいのかわかりません。
そして、はい、ConentProvider も可能性があることを知っています。しかし、それは私のアプローチでも機能するべきではありませんか? Android で InputStream ストリームを別のサービスに渡す他の方法はありますか?
余談ですが、CommonsWare は ContentProvider を使用して同様のプロジェクトを作成しました(関連する SO の質問1、2 )。私のアプローチのアイデアのほとんどはそこから得たものです