Android Audio Streaming

Having spent hours and hours trying to figure out how to get MediaPlayer to work properly on a thread for my last video project and now an audio streaming app, I found there’s an easier way.

The AsyncPlayer class takes care of this for you.

player = new AsyncPlayer(TAG);
player.play(this, Uri.parse(stream), false, AudioManager.STREAM_MUSIC);

For some reason the PocketJourney streaming tutorial for Android 1.0 keeps ranking in all my searches, which is generally too bad because that’s way out of date (incidentally, here is the newer version for 1.5 and later). You don’t need to buffer or double buffer media for the media player anymore. However, the comments on there helped me find AsyncPlayer as well and the 3GP file that Anthony posted to test this.

Now, the next step is to figure out how to get MediaPlayer (which underlays AsyncPlayer) to play an MP3 stream. I don’t know why it won’t, as MP3 is a supported type, but it plays nothing for my test stream.

Update Removed the link to the old streaming article in the hopes that the new one will rank better.

Update Android SDK doesn’t support streaming MP3 (shoutcast) until 2.2 (FroYo). To stream an MP3 stream on earlier OS versions you need to double buffer it either using the PocketJourney code above (which is not very good — it stutters) or using a built-in proxy as the NPR News app does.

20 thoughts on “Android Audio Streaming

  1. Well, I still haven’t figure out how to get the built in player to play a straight MP3 stream from an HTTP streaming server. So I grabbed the Pocket Journey double buffer streaming class and used that. It produces audio and plays the stream. Although it does seem to stutter every minute or so — I presume that’s the double buffering. I’ll keep working to clean it up.

  2. Per my update in the article, Android 2.1 and earlier won’t stream MP3 (Shoutcast) directly. I worked around it with a buffering proxy.

  3. Which kind of buffering proxy did you use to handle shoutcast streams ? Is it something similar to the NPR StreamProxy ?
    Do you mind share some technical details with us ?

  4. Freddy –
    I used the NPR Stream Proxy. It doesn’t actually buffer — all it does is change the “ICY/1.1” header to “HTTP/1.1” so that the media player will support it. If the app is running on 2.2 though, you don’t need this — the media player will play shoutcast streams directly.

  5. I tried the NPR solution on the emulator but it was not working at all on both 1.5 and 1.6 targets. Does it only work on mobile phones ?
    Thanks for your answer

  6. If you run the NPR Android App itself from source code, you’ll need to get an API key from NPR. This key will only allow you to play select media (but not everything).

    I have used the code from the NPR app in two other projects and was able to make it work in the emulator on 1.6, 2.1 and 2.2. I have not tried this on 1.5.

  7. Using the latest npr-android-app source code and a test case I was able to play your stream on a 1.6 emulator; although I got this message repeatedly, it still played:
    E/PlayerDriver( 31): Invalid percentage value ####

    On 1.5 it refused to play with this error.
    E/PlayerDriver( 542): Command PLAYER_INIT completed with an error or info PVMFErrCorrupt

    For the record, in both environments you have to use StreamProxy for this (i.e. set stream = true when calling PlaybackService.listen).

  8. On 1.5, I get the error you mentioned, but also some sockets errors (pipe broken …) .

    On 1.6, I get the “Invalid percentage value”, but I was unable to ear the sound. I’ll check again …

    Thanks

  9. You will always get “pipe broken” from the proxy any time that you cancel the connection to it. It’s a very simple proxy and that’s how it handles a broken connection. I suppose we could trap that error better.

    You might want to join the npr-android mailing list to discuss this. There are more knowledgeable folks about that codebase there.

  10. how can i play shoutcast streaming within my app. I used the code
    player = new AsyncPlayer(TAG);
    player.play(this, Uri.parse(stream), false, AudioManager.STREAM_MUSIC);
    But it plays only for few seconds. Do we have loop through the stream? Can you please post entire project for download?
    I am working on 2.2 froyo.

  11. I haven’t used AsyncPlayer in any projects because everything I’ve done I’ve needed more fine-grained control over (like pause and resume). What you show should work given what the documentation says.

    As noted above, you need 2.2 to play Shoutcast streams natively, but you say you are doing that. We’ve also had some trouble with streams stopping when the device switches radios (e.g. from wifi to cell service or 3G to EDGE). This shouldn’t be a problem in the emulator though.

  12. In froyo is AsyncPlayer supposed to play the radio station continuosly without need of a loop.
    I dont know how to put it in loop as there is no oncompletion listener to AsyncPlayer.
    How can I start stream from app directly.
    Fow now am downloading the stream bytes from stream and set the datasource of mediaplayer, prepare it and then add to a array as queue.
    Do I have to do the same in AsyncPlayer. I dont get how to do with AsyncPlayer.

  13. I can only assume from the documentation and the source that AsyncPlayer will play a steam non-stop as it’s just using the MediaPlayer underneath.

    There’s no reason you should need to download and buffer the data to the MediaPlayer. That’s a lot of overkill and lots of potential bugs in code you don’t need to write. 🙂

    In the AsyncPlayer.play call, you can pass a boolean to tell the player to loop; that is, start the media from the beginning when it ends. This doesn’t have any bearing on a stream, I don’t think, as the stream has no defined end.

    AsyncPlayer is just a wrapper around MediaPlayer for when you need very little control. If you want OnCompletionListener or any other events (which I suspect you would in any production use) you should probably use MediaPlayer directly.

    1. Thanks for prompt replies. I am trying to play shoutcast streams. So I guess due to ICY protocol there are breaks in stream. I downloaded the npr news app streamproxy code. Looks like we need to set up a proxy for running the code. Currently it does not work as it is.
      Now, I guess you must have seen the code too.(Judging by reply in stackoverflow)
      Can you post a tutorial on how to set up the npr news app and configure it on my current proxy?
      Where in streamproxy code should I put my proxy server address?
      How do I get the app to start working?
      Finally
      Is proxy necessary to get the streaming work on froyo for shoutcast streams?

  14. You don’t need a proxy on FroYo. If you look at the NPR News app, you’ll see that it only implements the proxy when running on OS < 2.2 and when reading a stream (as opposed to a file). The proxy merely changes the ICY/1.1 header to HTTP/1.1 so that the MediaPlayer won't puke.

    The best tutorial I can give you on the NPR app are the test cases in the trunk. While there's a fair bit of harness code (more than I like), the rest of the test case is pretty straightforward.

    Also, note, as of this writing, the entire NPR News app in trunk does not play stations — parts of the code are under re-organization. To get a fully working one, check out the branches/version_1.x. But the test cases in trunk work and should show how those components can be used.

  15. I did not know how to get rid of this error:

    (…)
    AwesomePlayer cache is running low (1.43seg), pausing
    (…)
    HttpStream recv failed, errno = 11 (Try again)
    NuCachedSource2 source returned error -1004
    (…)

    Now, thanks to your two lines, this only happens once, then I get:

    AwesomePlayer cache has filled up (1.34seg), resuming

    And the audio comes to live again, with no more cuts!

    Thank you man, seriously, thank you!!

Leave a reply to Freddy Cancel reply