Streaming with Android MediaPlayer - catching errors and buffering
I'm having trouble getting MediaPlayer
to be resilient when streaming from a HTTP URL.
If I start playing the file, but then drop the connection (e.g. airplane mode), MediaPlayer#OnErrorListener
generates what=1, extra=-17
and then shortly afterwards what=-38, extra=0
.
There's no documentation I can see in the APIs of what this denotes, except extra is "Typically implementation dependant". I'm using a HTC Hero (well, it's T-Mobile UK's G2 Touch).
Do other people get the same values and is it safe to catch these values as meaning the connection's gone?
How can I best resume when the connection reappears? (save the current seek to preferences, and retry every 5 seconds?)
How do I know when the device has decided to start playing what it's been buffering - is there a callback (other than polling isPlaying()
)?
Additionally, I'm not entirely sure what onBufferingUpdate
provides. I'm using a 40 minute podcast MP3 (64kbps bitrate)
- buffering goes 1%, 2%, 3%. When I seek to about 30 mins in, it shows 75%, then when I seek back to the start back to 5% - what is the point of this callback other than showing approximately what is cached?
Finally - is there any way to pipe what's streame开发者_Python百科d to an MP3
?
Taken from This similar stack Overflow Question
I too am disappointed about the MEDIA_INFO_BUFFERING_START and MEDIA_INFO_BUFFERING_END hooks... bummer.
I checked out the Pandora app and it doesn't display a buffering indicator. When music is interrupted for buffering, it just sits there as if nothing happened and the UI looks like it's still playing. So I've come to the conclusion that if you're using MediaPlayer, it's just not possible to determine if the track is temporarily paused for buffering.
However, I did notice that there are a couple MediaPlayer constants that could be of use: MEDIA_INFO_BUFFERING_START and MEDIA_INFO_BUFFERING_END. But they're only available in API level 9+, and the docs don't say anything about them. I'm assuming they can be used with an OnInfoListener.
I'm disappointed, but at least I can stop spinning my wheels now and move on to something else.
It is possible to do this
MediaPlayer has methods to register a OnPreparedListener and a OnBufferingUpdateListener
onPrepared will be called once the player has buffered enough to start playing.
http://developer.android.com/reference/android/media/MediaPlayer.OnPreparedListener.html
onBufferingUpdate will be called to update you on buffering information.
http://developer.android.com/reference/android/media/MediaPlayer.OnBufferingUpdateListener.html
You should also use the Connectivity service to listen for network connectivity
public boolean hasConnectivity()
{
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
int netType = info.getType();
int netSubtype = info.getSubtype();
if (netType == ConnectivityManager.TYPE_WIFI)
{
return info.isConnected();
}
else if (netType == ConnectivityManager.TYPE_MOBILE && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS)
{
return info.isConnected();
}
return false;
}
I think you should listne for loss/gain of network. Have a look at: Detect 3G or Wifi Network restoration
When you seek or skip or the connection is lost and MediaPlayer keeps reconnecting to the proxy server, you must send this response with Status 206 after you get the request and range(int) from the client.
String headers += "HTTP/1.1 206 Partial Content\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";
And when you receive a request from MediaPlayer that does not contain Range in the HTTP header , then it is requesting a new stream file, in this case your response header should look like this:
String headers = "HTTP/1.1 200 OK\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + fileSize + "\r\n";
headers += "\r\n";
Enjoy!
精彩评论