2010-01-27 60 views
14

内容提供者/解析器API提供了使用URI和openInputStream()openOutputStream()方法在进程间传输数据的复杂但稳健的方法。自定义内容提供商可以使用自定义代码覆盖openFile()方法,以便将URI有效解析为Stream;然而,openFile()的方法签名具有ParcelFileDescriptor返回类型,并且不清楚如何为动态生成的内容生成适当的表示以从此方法返回。定制ContentProvider - openInputStream(),openOutputStream()

Returning a memory mapped InputStream from a content provider?

是否有实现用于在现有的代码库动态内容ContentProvider.openFile()方法的实例?如果不是,你可以建议源代码或过程吗?

回答

1

MemoryFile支持此功能,但公共API尚未完成。

+0

是否有计划包括记忆文件和parcelfiledescriptor在未来?沿着这些线条的东西比用临时文件具有未知生命时间的文件系统混乱/污染更好。 也许有一些方法可以检测内容提供者内的流的关闭,这可以提供一种更安全的方式来清理自己? 我担心发送附件到(gmail/standaed)电子邮件客户端,虽然我确信还有其他地方可能会出现这些问题。 – hannasm 2010-01-29 03:18:09

+1

是的,MemoryFile.java目前有一个'public ParcelFileDescriptor getParcelFileDescriptor()'方法。这是甜甜圈的一部分,但正如杰夫所说,目前还没有最终确定。 我已经证实,“概念”至少可以工作,而且目前可以使用反射来完成。这是非常肮脏的,但不建议:) 不幸的是,即使'ParcelFileDescriptor.fromSocket()'不能使用,因为Memory.isMemoryFile()'抛出一个异常,因为套接字既不是PFD也不是内存文件。 – Joe 2010-07-03 09:11:47

+1

小心MemoryFile。如果我理解正确,它会将文件的全部内容存储在内存中,因此不能使用比可用内存大的文件。 – 2013-02-22 19:26:46

23

从总是乐于助人的CommonsWare中查看这个优秀的示例项目。它可以让你创建你想在一边不管的InputStream一个ParcelFileDescriptor管,而在另一侧的接收应用程序:

https://github.com/commonsguy/cw-omnibus/tree/master/ContentProvider/Pipe

关键部位在openFile创建管:

public ParcelFileDescriptor openFile(Uri uri, String mode) 
                 throws FileNotFoundException { 
    ParcelFileDescriptor[] pipe=null; 

    try { 
     pipe=ParcelFileDescriptor.createPipe(); 
     AssetManager assets=getContext().getResources().getAssets(); 

     new TransferThread(assets.open(uri.getLastPathSegment()), 
         new AutoCloseOutputStream(pipe[1])).start(); 
    } 
    catch (IOException e) { 
     Log.e(getClass().getSimpleName(), "Exception opening pipe", e); 
     throw new FileNotFoundException("Could not open pipe for: " 
      + uri.toString()); 
    } 

    return(pipe[0]); 
    } 

然后创建一个线程,保持管道充满:

static class TransferThread extends Thread { 
    InputStream in; 
    OutputStream out; 

    TransferThread(InputStream in, OutputStream out) { 
     this.in = in; 
     this.out = out; 
    } 

    @Override 
    public void run() { 
     byte[] buf = new byte[8192]; 
     int len; 

     try { 
      while ((len = in.read(buf)) > 0) { 
       out.write(buf, 0, len); 
      } 

      in.close(); 
      out.flush(); 
      out.close(); 
     } catch (IOException e) { 
      Log.e(getClass().getSimpleName(), 
        "Exception transferring file", e); 
     } 
    } 
} 
+3

完美正是我正在寻找的... – siliconeagle 2013-03-29 12:49:28

+0

我使用第三方库通过内容提供程序请求文件,由于某种原因,另一端的数据以不同的方式到达(在这里我一直在仔细地说) ParcelFileDescriptor以这种方式或使用像这样的真实文件时:ParcelFileDescriptor.open(privateFile,ParcelFileDescriptor.MODE_READ_ONLY) – TacB0sS 2015-04-10 13:39:07

+1

任何想法为什么我有时使用此提供程序与更大量的请求时出现错误: java.io.IOException:写入失败:EPIPE(Broken pipe) at libcore.io.IoBridge.write(IoBridge.java:502) at java.io.FileOutputStream.write(FileOutputStream.java:186) – Malachiasz 2015-09-04 12:09:15