views:

970

answers:

3

Hi. I'm trying to write a light-weight HTTP server in my app to feed dynamically generated MP3 data to the built-in Android MediaPlayer. I am not permitted to store my content on the SD card.

My input data is essentially of an infinite length. I tell MediaPlayer that its data source should basically be something like "http://localhost/myfile.mp3". I've a simple server set up that waits for MediaPlayer to make this request. However, MediaPlayer isn't very cooperative. At first, it makes an HTTP GET and tries to grab the whole file. It times out if we try and simply dump data into the socket so we tried using the HTTP Range header to write data in chunks. MediaPlayer doesn't like this and doesn't keep requesting the subsequent chunks.

Has anyone had any success streaming data directly into MediaPlayer? Do I need to implement an RTSP or Shoutcast server instead? Am I simply missing a critical HTTP header? What strategy should I use here?

Rob Szumlakowski

-- Later, I managed to solve the problem:

The HTTP Server was indeed hosted on the phone itself. It was very simple: just a thread listening on a socket for an HTTP GET request. When it got the HTTP request, it would one a new socket, write back some HTTP headers and start dumping the MP3 audio data back to the socket. This HTTP server didn't do anything else.

The Android Media Player was playing the music as I was streaming to it. The Media Player behaved very poorly if its playback buffer was emptied while it was playing audio. It was very important for me to make sure my HTTP server kept writing data into that socket. I moved bytes into the socket in small chunks (10 kB). The headers on my HTTP response ended up looking like this:

// Build response headers StringBuilder sb = new StringBuilder(); sb.append( "HTTP/1.1 200 OK\r\n"); sb.append( "Content-Type: audio/mpeg\r\n"); sb.append( "Connection: close\r\n" ); sb.append( "Accept-Ranges: bytes\r\n" ); sb.append( "Content-Length: " + totalFileSize + "\r\n" ); sb.append( "Content-Disposition: inline; filename=xxxxx.mp3\r\n\r\n");

As long as I kept the pipe stoked, the Android Media Player kept consuming it without complaint. Playing audio only required one request and response. It ended up working pretty well.

A: 

This guy has a good example of a streaming media player that buffers to a temp file. Maybe something from his tutorial can help you out. He's not using the built in media player, but he's using the Android MediaPlayer object which you can totally just wrap a simple UI around and make the same experience.

Rich
That tutorial is from April 2008, which means it is unlikely to run on modern Android without substantial modifications.
CommonsWare
The tutorial has since been updated with a follow-up article about differences in 1.5
Jessica
A: 

Hi Rob,

I appreciate this is a fairly old post but I've come across it whilst searching in vain for an answer to almost exactly the same question. I've been trying to get something very similar to what you've described working but with basically the same results.

Did you get the approach you're describing working or use another method?

Even if you can tell me that you simply couldn't get it working then I can completely discount this method.

Many thanks,

Gareth.

tafty
Wow that was indeed a while ago. I definitely got it to work with a simple HTTP server streaming to the Android Media Player. It was tricky to get it working. The Media Player was indeed very picky. In the end, we got it going such that the Media Player made one HTTP request and we responded once. Once we got the headers right, we just streamed all the data in one go. I'll respond to you directly with more info.
Rob Szumlakowski
A: 

Hi Rob, Any possibility that you could share how you did his? I'm currently having the same problem myself, and I'm starting to get realy frustrated :) Thanks!

greve
I've edited the question above to add more information regarding my solution. I hope it helps.
Rob Szumlakowski
Thanks, I hope it will work :)
greve