我试图找出一个录制音频的例子,数据存储由应用程序处理,而不是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) 有关我最近的问题MediaRecorder和createPipe()和的讨论createPipe()技术,这个其他SO问题,我现在正在试图获得MediaPlayer与所服务的内容合作ContentProvider通过ParcelFileDescriptor和createPipe().
这个示例项目是我迄今为止的工作.它基于较早的示例,该示例播放存储为原始资源的OGG剪辑.因此,我知道我的剪辑很好.
我已将MediaPlayer设置更改为:
private void loadClip() {
try {
mp=new MediaPlayer();
mp.setDataSource(this,
PipeProvider.CONTENT_URI.buildUpon()
.appendPath("clip.ogg")
.build());
mp.setOnCompletionListener(this);
mp.prepare();
}
catch (Exception e) {
goBlooey(e);
}
}
Run Code Online (Sandbox Code Playgroud)
通过登录PipeProvider,我发现我的Uri构建正确.
PipeProvider与此示例项目中的相同,适用于将PDF提供给Adobe Reader,这限制了我的代码的使用方式.:-)
具体来说,openFile()创建一个管道ParcelFileDescriptor:
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
ParcelFileDescriptor[] pipe=null;
try {
pipe=ParcelFileDescriptor.createPipe();
AssetManager assets=getContext().getResources().getAssets();
new …Run Code Online (Sandbox Code Playgroud) 既然fseek()不能在管道上运行什么方法来模拟前进?天真的方法是使用fread()并丢弃读入内存缓冲区的内容.为了避免巨大的缓冲区,你只需要使用缓冲区的一部分就可以反复使用相同的缓冲区.
但这是唯一的方法吗?还有另一种方法可以避免缓冲区和潜在的多次读取吗?
我在我的app资源目录中有一个pdf文件,我希望使用外部应用程序打开,所以写了我的内容提供商,我试着让它工作,但没有...
这是代码:
内容提供商:
package package.name;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
public class FileContentProvider extends ContentProvider {
private static final String URI_PREFIX = "content://package.name.filecontentprovider";
public static String constructUri(String url) {
Uri uri = Uri.parse(url);
return uri.isAbsolute() ? url : URI_PREFIX + url;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
URI uri1 = URI.create("file:///data/data/package.name/"+uri.getPath());
File file = new File(uri1.getPath());
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return parcel;
} …Run Code Online (Sandbox Code Playgroud)