Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android媒体播放器-如何禁用范围请求?(Nexus 7上的音频流中断)_Android_Streaming_Media Player - Fatal编程技术网

android媒体播放器-如何禁用范围请求?(Nexus 7上的音频流中断)

android媒体播放器-如何禁用范围请求?(Nexus 7上的音频流中断),android,streaming,media-player,Android,Streaming,Media Player,我有一个音频流应用程序,它运行一个本地代理服务器。本地代理服务器与internet流媒体源建立http连接,在本地获取并缓冲流媒体数据。 然后,在应用程序内部,我使用MediaPlayer连接到本地代理服务器,方法如下 mediaPlayer.setDataSource(...); // the url of the local proxy server 在Nexus7发布之前,一切都很好(有很多Android设备和不同的操作系统版本-1.5…4.0) 在Nexus7中,媒体播放器拒绝播放来自

我有一个音频流应用程序,它运行一个本地代理服务器。本地代理服务器与internet流媒体源建立http连接,在本地获取并缓冲流媒体数据。 然后,在应用程序内部,我使用MediaPlayer连接到本地代理服务器,方法如下

mediaPlayer.setDataSource(...); // the url of the local proxy server
在Nexus7发布之前,一切都很好(有很多Android设备和不同的操作系统版本-1.5…4.0)

在Nexus7中,媒体播放器拒绝播放来自本地代理服务器的源

当我查看日志时,似乎MediaPlayer在内部使用范围请求。 我的本地代理服务器不能处理这个问题。它返回HTTP/1.0 200 OK和数据。 但是,媒体播放器不喜欢这样,并抛出一个异常:

Caused by: libcore.io.ErrnoException
?:??: W/?(?): [ 07-18 00:08:35.333  4962: 5149 E/radiobee ]
?:??: W/?(?): : sendto failed: ECONNRESET (Connection reset by peer)
?:??: W/?(?):   at libcore.io.Posix.sendtoBytes(Native Method)
?:??: W/?(?):   at libcore.io.Posix.sendto(Posix.java:146)
?:??: W/?(?):   at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:
?:??: W/?(?):   at libcore.io.IoBridge.sendto(IoBridge.java:473)
We requested a content range, but server didn't support that. (responded with 200)
根据http规范,如果服务器响应http/1.0而不是1.1,则客户端不得触发范围请求(1.0无论如何都不支持该请求)

另外,如果服务器不支持范围请求,如果它响应200 OK(这就是我正在做的),那么应该可以,但是Nexus7上的MediaPlayer实现不喜欢这样

我看了一下这条线:

,他们声称200 OK的响应必须足够好,但不幸的是,这没有帮助

我不确定这是Jelly Bean的问题,还是Nexus7实现的问题,但这仍然是我必须解决的问题

同样,使用同一应用程序的许多其他Android设备上也没有范围请求。出于某种原因,这些范围请求现在正在Nexus7上发生。(这种情况也可能发生在其他安卓设备上,但同样,到目前为止,我从未遇到过)

是否有任何可能的方法来禁用MediaPlayer的范围请求

如果没有,是否有人可以建议快速修复我的代理服务器逻辑(如果它收到此范围请求,它必须返回什么?),而不更改我的其他逻辑(如果可能)

似乎我必须返回类似“HTTP/1.0 206 OK\r\nPartial Content\r\n\r\n”的内容,但可能在部分内容的末尾应该有一些值-不确定这应该是什么

谢谢你的帮助


谢谢..

我在一个大型音频流应用程序(使用本地主机HTTP代理将音频流到MediaPlayer)上工作,当我在Google I/O 2012上拿到一个JellyBean设备时,我就遇到了这个问题

当在不同的设备上对我们的应用程序进行质量测试时(以及使用从我们的自动崩溃日志和用户提交的日志中接收到的信息),我们注意到某些MediaPlayer实现的行为是我所说的不稳定的(有时是彻头彻尾的精神病)

我看到的是:有些实现会对同一个URL发出多个请求(有时是5+)。这些请求彼此略有不同,因为每个请求针对不同的字节范围(通常针对第一个或最后128个字节)。结论是MediaPlayer试图找到嵌入的元数据,然后在某一点之后它会放弃,只是发出一个常规的非范围请求

这不是stock JellyBean MediaPlayer实现所做的,它只是Android上媒体框架的古怪和普遍碎片化的一个例子。然而,上述情况的解决方案也是对果冻豆问题的解决方案,即:

让您的本地代理响应

这将使用transfer编码:chunked标头替换内容长度标头。这意味着请求的客户机将不知道资源的总长度,因此无法发出范围请求,它只需在接收到块时处理它们


就像我说的,这是一个黑客,但它的工作。这并不是没有副作用:媒体播放器缓冲区的进度将是不正确的,因为它不知道音频的长度(是其中之一),因此您必须使用自己的缓冲计算(您通过代理从某处流到媒体播放器,对吗?因此您将知道总长度).

我们终于以一种干净的方式解决了这个问题。在我们的例子中,我们可以完全控制流媒体服务器,但我想您也可以使用本地代理来实现这一点。由于
Build.VERSION\u CODES.ICE\u CREAM\u SANDWICH
可以为
MediaPlayer
对象设置标题。由于我们的应用程序允许用户在音频流中进行搜索,因此我们在客户端上实现了这个
范围
标题。如果服务器以正确的头响应,
MediaPlayer
将不会尝试多次请求流

这就是现在android客户端的服务器头的样子:

Content-Type: audio/mpeg
Accept-Ranges: bytes
Content-Length: XXXX
Content-Range: bytes XXX-XXX/XXX
Status: 206
重要的部分是
206
状态代码(部分内容)。如果您不发送此标头,android客户端将尝试重新请求源,无论发生什么情况


如果您的播放机不允许在流中搜索,您可以简单地将
范围
标题设置为
0-当您搜索或跳过或连接丢失且MediaPlayer继续重新连接到代理服务器时,任意大数

,从客户端获得请求和范围(int)后,必须发送状态为206的响应

String headers += "HTTP/1.0 206 OK\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + (fileSize-range) + "\r\n";
headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n";
headers += "\r\n";

我可以确认这是果冻豆问题(不仅仅是Nexus7)。它也发生在不同的Nexus设备上,最近从冰淇淋三明治升级到果冻豆。是否有人能够在Jelly Bean上对本地代理服务器使用MediaPlayer?也可以确认这个问题(在Jelly Bean上)。不过,我们没有使用代理,而是直接通过媒体播放器访问音频流。这看起来像是果冻豆的回归。我在bugtracker上创建了一个问题:这是一个有趣的方法来解决我在Je上遇到的问题