android media player - how to disable range request? (broken audio streaming on Nexus 7)

user1512464 picture user1512464 · Jul 23, 2012 · Viewed 8.9k times · Source

I have a audio streaming app, which runs a local proxy server. The local proxy server makes a http connection to a internet streaming source, gets and buffers locally the streaming data. Then, inside in the app, I use MediaPlayer to connect to the local proxy server, using the method

mediaPlayer.setDataSource(...); // the url of the local proxy server

Everything was fine (with plenty of Android devices and different OS versions - 1.5...4.0), until Nexus 7 release.

In Nexus 7, the media player refuses to play the source from the local proxy server.

When I took a look at the logs, seems like the MediaPlayer uses range requests internally. My local proxy server doesn't handle that. It returns HTTP/1.0 200 OK and the data. However, the media player doesn't like that and throws an exception:

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)

According to the http specs, if the server responds with HTTP/1.0 instead 1.1, the client must not fire a range request (1.0 doesn't support that anyway),

also if the server doesn't support the range request, it should be fine, if it responds with 200 OK (and this is what I'm doing), but the MediaPlayer implementation on Nexus 7 doesn't like that.

I took a look at this thread : HTTP: How should I respond to "Range: bytes=" when Range is unsupported?

,where they claim that the response with 200 OK must be good enough, but unfortunately it doesn't help.

I'm not sure if this is a problem with Jelly Bean, or a problem with Nexus 7 implementation specifically, but it's still a problem for me which I have to resolve.

Again, there are NO range requests on plenty other Android devices, using the same app. For some reason these range requests are happening now on Nexus 7. (It may happen on other Android devices as well, but again, never happened to me so far).

Any possible way to disable the range requests for MediaPlayer?

If there are none, can anybody suggest a quick fix for my proxy server logic (what exactly it has to return, if it receive this range request?), without changing my other logic, if possible?

Seems like maybe I have to return something like "HTTP/1.0 206 OK\r\nPartial Content\r\n\r\n", but probably there should be some value at the end of the Partial Content - not sure what is should be this one.

Your help would be appreciated.

Thanks..

Answer

pulse00 picture pulse00 · Nov 27, 2012

We've finally solved this in a clean way. In our case we have full control over the streaming server, but i guess you could do this with a local proxy as well. Since Build.VERSION_CODES.ICE_CREAM_SANDWICH it's possible to set headers for the MediaPlayer object. As our app enables the user to seek inside the audio stream, we've implemented this Range header on the client. If the server responds with the proper headers, the MediaPlayer will not try multimple times to request the stream.

That's what our server headers look like now for the android client:

Content-Type: audio/mpeg
Accept-Ranges: bytes
Content-Length: XXXX
Content-Range: bytes XXX-XXX/XXX
Status: 206

The important part is the 206 status code (partial content). If you don't send this header, the android client will try to re-request the source, no matter what.

If your player doesn't allow seeking in the stream, you could simply always set the Range header to 0-some arbitrary large number.