den*_*eli 42 audio streaming android audio-player android-music-player
我正在使用套接字作为MediaPlayer的代理,因此我可以在将mp3音频写入套接字之前下载并解密它.这类似于NPR新闻应用程序中显示的示例,但是我将其用于所有Android版本2.1 - 4 atm.
NPR StreamProxy代码 - http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java
我的问题是2.1-2.3的播放速度很快,但在Android 4.0 ICS中,MediaPlayer在触发onPrepared监听器之前会缓冲太多数据.
在onPrepared()之前写入Socket OutputStream的示例数据量:
在SGS2上有2.3.4 - onPrepared()在~133920字节之后
在Nexus S上使用4.0.4 - onPrepared()在~961930字节之后
这也发生在Galaxy Nexus上.
奇怪的是,4.0模拟器不会像4.0设备一样缓冲数据.有人在ICS上遇到与MediaPlayer类似的问题吗?
编辑
以下是代理如何写入套接字.在这个例子中,它来自从文件加载的CipherInputStream,但是当它从HttpResponse加载时也是如此.
final Socket client = (setup above)
// encrypted file input stream
final CipherInputStream inputStream = getInputStream(file);
// setup the socket output stream
final OutputStream output = client.getOutputStream();
// Writing the header
final String httpHeader = buildHttpHeader(file.length());
final byte[] buffer = httpHeader.getBytes("UTF-8");
output.write(buffer, 0, buffer.length);
int writtenBytes = 0;
int readBytes;
final byte[] buff = new byte[1024 * 12]; // 12 KB
while (mIsRunning && (readBytes = inputStream.read(buff)) != -1) {
output.write(buff, 0, readBytes);
writtenBytes += readBytes;
}
output.flush();
output.close();
Run Code Online (Sandbox Code Playgroud)
在音频之前写入MediaPlayer的HTTP标头..
private String buildHttpHeader(final int contentLength) {
final StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\r\n");
sb.append("Content-Length: ").append(contentLength).append("\r\n");
sb.append("Accept-Ranges: bytes\r\n" );
sb.append("Content-Type: audio/mpeg\r\n");
sb.append("Connection: close\r\n" );
sb.append("\r\n");
return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)
我已经四处寻找替代实现,但由于我已经加密了音频并且MediaPlayer不支持InputStreams作为数据源,我唯一的选择(我认为..)就是使用这样的代理.
再次,这在Android 2.1 - 2.3上工作得相当好,但在ICS中,MediaPlayer在播放之前缓冲了大量此类数据.
编辑2:
进一步测试显示,一旦升级到Android 4.0.3,这也是SGS2上的一个问题.因此,似乎MediaPlayer的缓冲实现在4.0中发生了重大变化.这令人沮丧,因为API无法改变行为.
编辑3:
安装了Android bug.请添加评论并在那里加注星标 http://code.google.com/p/android/issues/detail?id=29870
编辑4:
我的播放代码是相当标准的..我在onPrepared()方法中对MediaPlayer进行了start()调用.
mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mCurrentPlayer.setDataSource(url);
mCurrentPlayer.prepareAsync();
Run Code Online (Sandbox Code Playgroud)
尝试使用just()和ajacian81的推荐方法,但无济于事.
我应该补充说,最近有一位谷歌员工回答了我的问题,并确认ICS中的缓冲区大小是有意增加的(对于高清内容).已经要求API开发人员添加在MediaPlayer上设置缓冲区大小的功能.
虽然我认为这个API更改请求在我出现之前已经存在,所以我不建议任何人屏住呼吸.
是否可以看到启动 MediaPlayer 的代码?
您使用的是STREAM_MUSIC音频流类型吗?
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
Run Code Online (Sandbox Code Playgroud)
您是否也尝试过player.prepareAsync(); 和player.prepare();?
我记得去年有一个类似的问题,解决方案是:开始,暂停,然后 onPrepared to start():
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(src);
player.prepare();
player.start();
player.pause();
player.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
Run Code Online (Sandbox Code Playgroud)
在这种情况下不太可能解决这个问题,但是当你正在旋转的时候,这可能值得一试。