Android Mediaplayer:下载媒体文件的 setDataSource 问题
Posted
技术标签:
【中文标题】Android Mediaplayer:下载媒体文件的 setDataSource 问题【英文标题】:Android Mediaplayer: setDataSource issue for downloaded media file 【发布时间】:2011-02-17 09:36:06 【问题描述】:我有一个可以录制和播放音频文件的应用程序。一些音频文件是使用 httpclient 使用简单的标准 http 下载来下载的。很长一段时间,它就像一种魅力。现在突然间我无法播放我下载的文件。这个堆栈失败了。我将文件存储在 SDCard 上,但我在手机和 USB 连接设备上都遇到了问题。
我已经检查了下载的文件在服务器上很酷,我可以毫无问题地播放它。
这些是我使用的代码 sn-ps(我知道recordingFile 是文件的有效路径)。
// inside the activity class
private void playRecording() throws IOException
File recordingFile = new File(recordingFileName);
FileInputStream recordingInputStream = new FileInputStream(recordingFile);
audioMediaPlayer.playAudio(recordingInputStream);
这是媒体播放器代码:
// inside my media player class which handles the recordings
public void playAudio(FileInputStream audioInputStream) throws IOException
mediaPlayer.reset();
mediaPlayer.setDataSource(audioInputStream.getFD());
mediaPlayer.prepare();
mediaPlayer.start();
这是一个例外:
E/MediaPlayerService( 555): offset error
E/MediaPlayer( 786): Unable to to create media player
W/System.err( 786): java.io.IOException: setDataSourceFD failed.: status=0x80000000
W/System.err( 786): at android.media.MediaPlayer.setDataSource(Native Method)
W/System.err( 786): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:632)
W/System.err( 786): at net.xxx.xxx.AudioMediaPlayer.playAudio(AudioMediaPlayer.java:69)
W/System.err( 786): at net.xxx.xxx.Downloads.playRecording(Downloads.java:299)
W/System.err( 786): at net.xxx.xxx.Downloads.access$0(Downloads.java:294)
W/System.err( 786): at net.xxx.xxx.Downloads$1.onClick(Downloads.java:135)
我已经尝试寻找偏移错误的一些答案,但不太清楚这个问题可能是什么。
PS 我用这个代码下载文件:
public FileOutputStream executeHttpGet(FileOutputStream fileOutputStream) throws ClientProtocolException, IOException
try
// Execute HTTP Post Request
httpResponse = httpClient.execute(httpPost, localContext);
int status = httpResponse.getStatusLine().getStatusCode();
// we assume that the response body contains the error message
if (status != HttpStatus.SC_OK)
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
httpResponse.getEntity().writeTo(ostream);
fileOutputStream = null;
else
InputStream content = httpResponse.getEntity().getContent();
byte[] buffer = new byte[1024];
int len = 0;
while ( (len = content.read(buffer)) > 0 )
fileOutputStream.write(buffer,0, len);
fileOutputStream.close();
content.close(); // this will also close the connection
catch (ClientProtocolException e1)
// TODO Auto-generated catch block
e1.printStackTrace();
fileOutputStream = null;
catch (IOException e2)
// TODO Auto-generated catch block
e2.printStackTrace();
fileOutputStream = null;
return fileOutputStream;
【问题讨论】:
【参考方案1】:我自己解决了。正如我所说,我对解决方案的评论是这样的:
当我重构部分代码时,我在用于允许下载但不允许下载的哈希码上打错了字。不幸的是,当我下载强制文件为空的文件时,我没有正确的捕获。基本上,如果您尝试在没有正确激活码的情况下检索文件,我会发送错误的请求标头。
罪魁祸首在这里:
if (status != HttpStatus.SC_OK)
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
httpResponse.getEntity().writeTo(ostream);
fileOutputStream = null;
else
InputStream content = httpResponse.getEntity().getContent();
byte[] buffer = new byte[1024];
int len = 0;
while ( (len = content.read(buffer)) > 0 )
fileOutputStream.write(buffer,0, len);
fileOutputStream.close();
content.close(); // this will also close the connection
对于状态代码返回错误的情况(即,被阻止访问的错误请求标头)。我错过的是在那里捕获空指针的情况,这导致 SQLite 条目被更新,声称下载成功但没有成功。
经验教训:即使是原型,也要始终对这些情况进行空检查。 :-)
【讨论】:
【参考方案2】:首先,确保您的设备未安装。 Android 或主机 PC 都可以访问 SD 卡,但不能同时访问。
其次,不清楚您为什么使用FileInputStream
和getFD()
。只需将 SD 卡上文件的路径传递给MediaPlayer
(例如new File(Environment.getExternalStorageDirectory(), "yourfile.mp3")
),然后让播放器打开文件。
【讨论】:
感谢您的回答。但是我发现了这个问题,这与调用后不检查 fileOutputStream 的空指针无关。我有一个网络服务器,可以让不同的播放列表保持同步。当我重构部分代码时,我在用于允许下载而不是允许下载的哈希码上打错了字。不幸的是,当我下载文件强制文件为空时,我没有正确捕获。基本上,如果您尝试在没有正确激活码的情况下检索文件,我会发送错误的请求标头。现在已经解决并且工作正常。 :-) 我使用 getFD 来确保我可以打开文件,而不必担心权限问题。在处理 SDCard 上的文件时,我发现这样做“更安全”。 在某些设备上(真的!)媒体播放器(位于单独的进程中)无法访问应用程序私有文件。我尝试播放下载到应用程序内部缓存的 MIDI 文件。并且媒体播放器向 logcat 发出“(Permission denied)”。 @yuku:使用FileProvider
。
@CommonsWare 谢谢!目前我使用 new FileInputStream(theprivatefile).getFD() ,然后将其传递给采用 FD 的 setDataSource。至少它适用于我尝试过的 Android 2.3、4.1、4.4。以上是关于Android Mediaplayer:下载媒体文件的 setDataSource 问题的主要内容,如果未能解决你的问题,请参考以下文章
Android -- 多媒体播放之MediaPlayer使用内部实现简析
Android多媒体-MediaPlayer唤醒锁及音频焦点