Home

Raw Audio

I am not an android developer. I am not even a Java developer. What appears below is my attempt to share what I’ve learned using the android documentation, google, and copious amounts of trial and/or error. I apologize for mistakes; please offer corrections via twitter or email.

I was upset when I first got my Droid Eris that the media player couldn’t load a url by default. I stream my mpd out to the world so that I can pick it up away from home. I had read that the built-in MediaPlayer object in android supports any uri that offered progressive download of media in a format supported by the device (both ogg and mp3 are supported). So why not expose this feature in the UI?

I soon found out that the only way to play a custom audio stream from the internet was to purchase StreamFurious Pro. Not a bad app, but overkill for my situation. I had to load up this internet radio player with all these built in stations just to load my own custom url. I then had to wait literally minutes while it buffered a hard-coded ~5MB before beginning to play. Garbage.

So why not write my own?

Android

I decided to take this as an opportunity to get my feet wet with Android (and Java in general). I figured I could write a simple App to accept a URL entered into a text box and load it using the built-in MediaPlayer() class. Because of the underlying simplicity, you could even pass file:///foo/bar.mp3 and it would work.

Well, I did that. And it even works surprisingly well; I figured I could post what I’ve done, and hopefully it’ll be useful to others.

Activities and Services

My App would use two of the major building blocks in Android: Activities and Services.

An Activity is the object, the class, that runs when you first open your UI. It basically is the UI. It handles accepting user input and doing something with it. It’s designed to only be Active while the user is viewing your UI. Once your App closes, it can and will be safely killed.

So what if you need to do some persistent background work? Like, say, playing music? That requires a Service.

A Service is another class that runs in the background. It can be created, bound to, and controlled by your Activity. It gets a slightly higher priority in the grand scheme of things, so it’s less likely to get killed when the user’s not interacting with your Activity.

The IDE

First, let me describe a little bit about my development environment because it handles a lot of the back-end stuff that I’m not going to touch on here.

First thing I did was install a few packages. Android-sdk of course, eclipse-android (available in the AUR to Arch users), and a nice little package called eclim.

Eclim is awesome. It’s a vim plugin that let’s me hook into eclipse from within vim. I can do all my coding in my favorite editor ever, and let eclipse handle the heavy lifting. Things like: auto-completion of method names, automatic imports, syntax checking, and documentation lookups.

I also hop back over to eclipse to do my compiling, and installation.

I’ll leave setting up your sdk and eclipse project to you since there’s a ton of OS/distro-specific ways to do it; google is your friend.

The UI

It’s possible to define your UI programmatically from within your main Activity. This is frowned upon and not only is it a best practice but it’s also wicked convenient to define your UI via an xml file instead.

Under your project directory are two very important sub-directories: src and res. In your src folder is the actual Java source, and in your res directory are your resources. Things like images, static string values, and xml layout files. With a vanilla package template, your UI is defined in res/layout/main.xml.

Here’s my res/layout/main.xml:

Here I’ve defined a layout where objects are placed relative to each other, with a TextView label with id “label”, an EditText entry box with id “entry”, and a single Play/Pause button with id “playpause”.

You’ll also notice I use the @string/foo convention. This means pull the value from the res/values/strings.xml file.

Here’s mine:

So @string/play_pause is a variable for “Play/Pause”.

I pre-populate @id/entry with my server’s address (@string/my_server). I only need this App to pickup my mpd stream, so why should I always have to type it? This way, it’s there, but I can overwrite it if I want to.

The Activity

Now that that’s out of the way, onto the Java.

I define a class RawAudio which extends the Android base class Activity.

One thing I do differently is implement OnClickListener. I picked this up in one of my google results, and I find it to be a much cleaner approach to button handling.

This allows us to assign the keyword this (meaning the very class that we are) as an OnClickListener for any of our buttons. That way, when we click that button, our very own onClick() will be called.

I know what your thinking: But, what if you have more than one button? Don’t you need an OnClickListener for each of them? Of course not; onClick() is passed a view that corresponds to the button that was clicked, so with a simple switch statement we could determine what button was clicked and act accordingly.

Sweet, I know, but I’ve only got one button so I don’t do that here. Anyway, here’s the top portion of my RawAudio class:

First we have our overridden onCreate() call. This method is run when your App is launched. You can think of it like main() or run() from other languages. There are other important “lifecycle” methods you should look into, but this and onDestroy() are the only two I use here.

I use this starting point to setup my UI based on main.xml via setContentView(). Notice the argument is almost literal: R.layout.main -> res/layout/main.xml.

I also create a Button object based on R.id.playpause from our main.xml file and set this as its onClickListener.

Lastly, I connectToService().

So at this point time-wise, I can assume that my UI is loaded and I’m connected to my service, ready for user input.

The other overridden method is onDestroy(). This is called when your App is exited or killed. The only reason I need to override it is so that I can disconnect from the service. unbindService() is a built-in method that I don’t need to define, I just have to call it. onService will be defined later.

Now that I’ve mapped things out at a high level, all that’s left is to fill in the blanks: what to do onClick(), how to connectToService(), etc.

So take a break, make sure you’ve understood up to this point, then continue onto the “plumbing” below.

Play/Pause

I decided to leave the logic of how to handle a Play/Pause “event” up to the Service. I would send over the command, and it would determine if it should load or pause a stream by its current internal state.

For this reason, onClick() is fairly simple. We get the stream url from the text box, pass it and this as arguments to a Service method.

I’ll explain more when we get to it. But basically, streamMusic is an instance of our service. It will be null when we’re not connected to the service. It also has the public method playPause() which will be written to accept a context (this) and a stream url. It will take the appropriate action of loading, pausing, or resuming the stream.

We’ve left the most important piece for last. I’m not going to say much because I don’t fully understand it, but it’s pretty copy/paste-able code for situations where you need to bind to a service. All I know is that it instantiates streamMusic on connect and resets it to null on disconnect; that’s good enough for me.

For this to work, you have to define StreamMusic.LocalBinder when you write your Service, but I’ll get to that…

That’s it for our Activity. I hope all that made sense. It’s all quite useless however without our Service.

The Service

Besides actually creating and using the Service, you also have to add a service tag to your manifest. Here’s my AndroidManifest.xml.

Eclipse took care of all of that save for the android:icon and service tags which I added by hand.

If you’re using an eclipse-eclim-vim setup like I am, don’t edit the Manifest in vim. Since it’s used to do the precompiling in eclipse, it somehow gets ahead of itself and throws errors. Just edit that one in eclipse directly.

My Service at this point does a few things:

That last piece is why we need to pass this in the playPause() method.

So the first thing we do is setup that binder voodoo that I still don’t fully understand ;). I’ll also override onDestroy() to stop the music.

Next up, we define the main interface with our activity: the playPause() handler.

Here you can see why we passed the UI Context in with the stream. Our progress notification needs a context in which to display itself. And if it’s not the main UI context, your App crashes. By simply passing this along to the service we can easily deploy our progress notification to it. Pretty sweet.

I’m not sure if synchronized is strictly needed but it was in the code I was working from and it makes sense logically. I haven’t tested omitting it so who knows.

Loading…

Again, we save the meat for last. The following two methods do some special things.

First, we setup and run the actual mediaPlayer in its own thread. We define a Runnable object with a run() that does the actual work. Then we use the Thread class to start it. Don’t ask me how it works, just copy the code :).

You can see when the stream loads, we call handler.sendEmptyMessage(0). This is because we can’t directly dismiss our progress notification from inside that thread. We need to somehow let the external context know that we’re done. We send out an empty message to a handler which actually dismisses the notification:

And there you go; Service done.

Screenshots

As always, the obligatory screenshots.

Raw Audio 

Raw Audio Progress 

References

Sadly, I can’t track down all the various google results that I used while writing this thing but here are a few I could dig up.

28 May 2010, tagged with android