JNI中的ParcelFileDescriptor.createPipe

时间:2017-03-22 14:08:42

标签: java android java-native-interface

我正在试图弄清楚如何在ContentProvider.openFile内传递数据流。要发送的数据是在JNI中创建的。我尝试使用传输线程createPipe,但是管道坏了我遇到了很多麻烦。所以我想我可能只是将'write'管道传递给JNI并直接将数据写入它。

爪哇:

ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
boolean result = ImageProcessor.getThumb(fd/*source fd*/, pipe[1].getFd()); //JNI call (formerly returned a byte[])
return pipe[0];

C:

unsigned char* jpeg = NULL;
unsigned long jpegSize = 0;

getThumbnail(env, &jpeg, &jpegSize, rawProcessor); // Populates jpeg thumb, works when converted to byte[] in second segment
FILE* out = fdopen(dest, "wb");
int written = fwrite(jpeg, 1, jpegSize, out);
return TRUE;

当我转换为byte []时,一切正常,但显然不在ContentProvider范围内:

jbyteArray thumb = env->NewByteArray(jpegSize);
env->SetByteArrayRegion(thumb, 0, jpegSize, (jbyte *) jpeg);
free(jpeg);
return thumb;

当我调试它到达fwrite时,堆栈跟踪似乎消失了。永远不会点击return TRUEreturn pipe[0],但也不会崩溃或抛出。很奇怪......

有没有人做过类似的事情?简单地将二进制文件写入“写入”管道是否足够?我在做什么根本上错了吗?感谢。

更新(与@pskink讨论后)

我尝试实施PipeDataWriter。我以FileProvider.java为例。

@Override
public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable byte[] args)
{
    try (FileOutputStream fout = new FileOutputStream(output.getFileDescriptor()))
    {
        fout.write(args, 0, args.length);
    }
    catch (IOException e)
    {
        Log.e(TAG, "Failed transferring", e);
    }
}
byte[] rawData = ImageUtil.getRawThumb(fd.getParcelFileDescriptor().getFd());
return openPipeHelper(Uri.parse("invalid"), "image/jpg", null, rawData, this);

但是,当我使用上面的传输线程时,我得到了同样的错误:

  

java.io.IOException:写入失败:EBADF(错误的文件描述符)
  在libcore.io.IoBridge.write(IoBridge.java:498)
  at java.io.FileOutputStream.write(FileOutputStream.java:186)
  在   com.anthonymandra.content.MetaProvider.writeDataToPipe(MetaProvider.java:273)

  

java.io.IOException:写入失败:EPIPE(断管)
  在libcore.io.IoBridge.write(IoBridge.java:498)
  at java.io.FileOutputStream.write(FileOutputStream.java:186)
  在   com.anthonymandra.content.MetaProvider.writeDataToPipe(MetaProvider.java:273)

当我介入以确保数据对图像没问题时,我发现所有东西都很好。在我看来,这实际上是一个线程安全问题。

1 个答案:

答案 0 :(得分:0)

实际上有一堆事情出了问题,所有这些都卷成了混乱的混乱:

  1. 我没有关闭最终的ParcelFileDescriptor
  2. 我使用Glide作为图片缓存,并在您加载Uri时使用两个获取器,这意味着openFile正在called twice per file
  3. (2)造成无休止的管道错误。
  4. StrictMode因为(1)而杀了该应用,我在(3)的一连串错误中错过了它。