Android 自定义ContentProvider-openInputStream(),openOutputStream()
内容提供者/解析器API使用URI和Android 自定义ContentProvider-openInputStream(),openOutputStream(),android,file-io,android-contentprovider,Android,File Io,Android Contentprovider,内容提供者/解析器API使用URI和openInputStream()和openOutputStream()方法提供了一种复杂但健壮的在进程之间传输数据的方法。自定义内容提供程序能够使用自定义代码覆盖openFile()方法,以有效地将URI解析为流;但是,openFile()的方法签名有一个ParcelFileDescriptor返回类型,不清楚如何为从该方法返回的动态生成的内容生成适当的表示 是否有在现有代码库中为动态内容实现ContentProvider.openFile()方法的示例?
openInputStream()
和openOutputStream()
方法提供了一种复杂但健壮的在进程之间传输数据的方法。自定义内容提供程序能够使用自定义代码覆盖openFile()
方法,以有效地将URI解析为流
;但是,openFile()
的方法签名有一个ParcelFileDescriptor
返回类型,不清楚如何为从该方法返回的动态生成的内容生成适当的表示
是否有在现有代码库中为动态内容实现
ContentProvider.openFile()
方法的示例?如果没有,您能推荐源代码或流程吗?MemoryFile支持这一点,但公共API尚未最终确定。请从总是有用的公共软件中查看这个伟大的示例项目。它允许您创建一个ParcelFileDescriptor管道,其中一端包含所需的任何InputStream,另一端包含接收应用程序:
关键部分是在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);
}
}
}
是否计划在将来包含memoryfile和parcelfiledescriptor之间的转换?沿着这些思路做的事情比用具有未知生命周期的临时文件混乱/污染文件系统要好。也许有某种方法可以检测到内容提供商内的流关闭,这可以提供一种更安全的方法来在您之后进行清理?我关心的是将附件发送到(gmail/standaed)电子邮件客户端,尽管我确信还有其他地方可能出现这些问题。是的,MemoryFile.java目前有一个
公共ParcelFileDescriptor getParcelFileDescriptor()
方法。这是作为甜甜圈的一部分承诺的,但正如杰夫所说,还没有最终确定。我已经证实了“概念”至少是有效的,并且目前可以使用反射来完成。但是它非常脏,不推荐使用:)不幸的是,即使是ParcelFileDescriptor.fromSocket()
也不能使用,因为Memory.isMemoryFile()
会引发异常,因为套接字既不是PFD也不是内存文件。请小心使用MemoryFile。如果我理解正确,它会将文件的全部内容存储在内存中,因此您不能使用比可用内存大的文件。我使用第三方库,通过内容提供商请求文件,出于某种原因,另一端的数据会到达(我在这里谨慎地说)以这种方式返回ParcelFileDescriptor或使用真实文件(如:ParcelFileDescriptor.open(privateFile,ParcelFileDescriptor.MODE_READ_))时会出现不同的情况。知道为什么在使用此提供程序处理大量请求时有时会出现错误吗:java.io.IOException:写入失败:Epie(断管)在libcore.io.IoBridge.write(IoBridge.java:502)和java.io.FileOutputStream.write(FileOutputStream.java:186)中,我遇到了与Malachiasz相同的问题。有人在这方面有什么进展吗?同样看到这个错误,您在3年后找到了解决方法吗?这确实有效,但比在文件系统上缓存文件要慢