很多Intent动作,例如ACTION_VIEW,Uri指向应该执行动作的内容.如果内容由文件支持 - 无论是Uri直接指向文件还是ContentProvider服务文件(请参阅参考资料FileProvider) - 这通常都有效.
在某些情况下,开发人员不希望将内容驻留在文件中以与其他应用程序共享.一种常见的情况是加密:解密的数据应该驻留在RAM中,而不是磁盘上,以最大限度地降低某人获取该解密数据的风险.
我从RAM共享的经典解决方案是使用ParcelFileDescriptor和createPipe().但是,当响应ACTION_VIEW(或其他)的活动获得InputStream该管道时,与ContentProvider从文件提供内容时获得的流相比,生成的流受到限制.例如,此示例应用程序适用于Adobe Reader并崩溃QuickOffice.
基于过去的 相关问题,我的假设是createPipe()真正创建一个管道,并且管道是不可寻找的.试图"倒带"或"快进"的客户因此遇到问题.
我正在寻找一种可靠的解决方案,用于与第三方应用程序共享内存内容,以解决此限制.特别:
它必须使用Uri可能被客户端应用程序(即ACTION_VIEW实现者)尊重的语法; 涉及客户端应用程序不太可能识别的某些麻烦的解决方案(例如,通过Intent额外的方式传递某些内容)不符合条件
要共享的数据不能作为共享的一部分写入文件(当然,客户端应用程序最终可以将收到的字节保存到磁盘,但暂时忽略该风险)
理想情况下,它不涉及应用程序寻求共享数据开放ServerSocket或以其他方式加剧安全风险
可能建议的想法包括:
某种重新配置的方法会导致可createPipe()搜索的管道
某种使用基于套接字的方法FileDescriptor可以产生可搜索的管道
某种RAM磁盘或其他东西,感觉像Android的其余部分的文件,但不是持久的
如果你愿意的话,一个关键的工作解决方案就是如果我可以从RAM中获得QuickOffice可以读取的PDF.
有什么建议?
谢谢!
我试图找出一个录制音频的例子,数据存储由应用程序处理,而不是MediaRecorder.用例包括将记录存储在内部存储器或加密记录.
原则上,这应该使用createPipe()on 创建的管道ParcelFileDescriptor,但我得到输出格式错误.
首先,这是一个示例项目,使用"自然"记录MediaRecorder,MediaRecorder直接写入外部存储上的输出文件.这个应用程序工作得很好,输出可以由记录它的Android设备或我的Linux机器上的VLC播放.
这是我createPipe()对这个项目的变化.从一般MediaRecorder配置(例如setOutputFormat())的角度来看,它与第一个相同,因此代码可能是正确的.
但是,我通过以下方式提供输出:
recorder.setOutputFile(getStreamFd());
Run Code Online (Sandbox Code Playgroud)
在getStreamFd()使用的地方createPipe(),产生一个后台线程来从管道中读取,并返回写入结束以供以下用户使用MediaRecorder:
private FileDescriptor getStreamFd() {
ParcelFileDescriptor[] pipe=null;
try {
pipe=ParcelFileDescriptor.createPipe();
new TransferThread(new AutoCloseInputStream(pipe[0]),
new FileOutputStream(getOutputFile())).start();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
}
return(pipe[1].getFileDescriptor());
}
Run Code Online (Sandbox Code Playgroud)
TransferThread是一个经典的java.io流到流复制例程,增加了智能来刷新和同步输出文件:
static class TransferThread extends Thread {
InputStream in;
FileOutputStream out;
TransferThread(InputStream in, FileOutputStream out) {
this.in=in; …Run Code Online (Sandbox Code Playgroud) 我想通过使用ParcelFileDescriptor.createPipe()一个流到流的复制线程和一个ParcelFileDescriptor,将一个Android服务从一个Android服务"发送"到一个不同进程中运行的另一个服务,该表示管道的读取端,它被提供给另一个服务借助Binder IPC.
我想将一个给定的InputStream发送到接收服务:
public sendInputStream() {
InputStream is = ...; // that's the stream for process/service B
ParcelFileDescriptor pdf = ParcelFileDescriptorUtil.pipeFrom(is);
inputStreamService.inputStream(pdf);
}
Run Code Online (Sandbox Code Playgroud)
ParcelFileDescriptorUtil是一个帮助器类,具有经典的java.io.流到流复制线程:
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 …Run Code Online (Sandbox Code Playgroud) 我正在创建一个输入流来缓冲和流式传输来自云的mp3.
URL url = new URL("http://xxxx.yyy.com/Demo.mp3");
InputStream inputStream = url.openStream();
Run Code Online (Sandbox Code Playgroud)
现在我如何从媒体播放器播放mp3而不使用临时文件来存储它并从同一回读?我正在为Android Lollipop开发
我知道在SO上已经有一些类似的问题,但是它们与播放文件之前提取文件有关。
在此处的Android文档中,它说明您可以直接从.zip文件播放文件,而无需将其解压缩。
提示:如果要将媒体文件打包为ZIP,则可以对具有偏移量和长度控件(例如MediaPlayer.setDataSource()和SoundPool.load())的文件使用媒体播放调用, 而无需解压缩ZIP。为了使它起作用,在创建ZIP软件包时,不得对媒体文件执行其他压缩。例如,使用zip工具时,应使用-n选项来指定不应压缩的文件后缀:
zip -n .mp4; .ogg main_expansion media_files
我已经制作了一个(未压缩的)zip程序包,但是我无法弄清楚如何从ZipEntry到FileDescriptor,而且他们也没有进一步解释。我如何在FileDescriptor不解压缩zip文件的情况下获得文件?