Music & Audio is one of the top 10 categories on Android with beautiful applications like Rdio that takes advantage of great native audio features such as Background Streaming to create an amazing user experience. It is extremely easy to get audio streaming in a background service with Xamarin.Android. Using a service to stream audio has many advantages like the ability to play audio while your application is not visible or under the lock screen.

To get started, let’s create our first Android Service with just a tiny amount of code:

I added a MediaPlayer to the service, which is used for audio playback on Android. The MediaPlayer will be used to start and stop playback as well as give us information such as the current position and duration of the audio that is being played. With the service setup we will need a way to communicate with it from our user interface. The best way to do this is to create Intent Filters with custom actions that can be passed from the user interface down to the service:

I added a few here for the example, but you may want to add other actions to your app such as skip forward/back. When your service receives a start command it will be passed an intent with one of our actions. Here I simply apply a switch case to the action and then call a private method I created for each action:

Then to send one of these actions from the user interface, all we have to do is start the service with the desired action:

I also created a simple user interface with buttons that when clicked will pass down these actions to the service:

StreamingMainUI

Starting and Stopping Playback

To start playback in the Play(); method we first initialize the MediaPlayer which allows us to specify what type of audio stream it accepts, and setup event handlers when the player has prepared a file, completed a file, or an error has occurred:

After the player has been initialized we simply set the datasource (mp3 url) and prepare the player for playback. After the player has prepared our file the Prepared event will be fired. Then we will start playback:

Stopping and pausing is as simple as calling the Stop() and Pause() methods on the player. After stopping playback it is important to also call the Reset() method on the player to set it back to an uninitialized state. Failing to reset the player can lead to exceptions when re-initializing with a new song.

Always be streaming

Even though we are in a service streaming audio Android itself has the ability to shut down or deprioritize features such as WiFi or the CPU. To tell Android we are doing something important we need to do two things. First, set a WakeMode on the player telling Android to keep the CPU alive:

and add a WakeLock permission in your AssemblyInfo.cs

Next, acquire a WifiLock to ensure that the WiFi be kept alive as well. When audio is playing you should acquire the lock, and when audio is stopped or paused you should release it.

Play on the Foreground

Our service isn’t a typical short lived task service like checking Twitter or email where users might not be aware that they are running. Audio is playing and there is a good chance that your users will want to interact or at least find out what application is playing the audio. This is where running our service as a foreground service comes in. A foreground service has a higher level of importance inside of Android and it will likely not kill off the service. Running in the foreground also means we can display an active notification and icon in the status bar.

After we start playback we will create our notification to display to our user. When this notification is tapped, it will launch our MainActivity which has our transport controls on it.

When we pause or stop playback, we want to call StopForeground(true); to tell Android to no longer run our service on the foreground and to remove the notification.
StreamingNotification

StreamingMiniNotification

Handling Audio Focus
Since Android is a multitasking environment, there may be several applications fighting for control of playing back audio. Android deals with this by allowing applications to handle audio focus changes that notify them to start, stop, or lower the volume of their audio. Implementing AudioManager.IOnAudioFocusChangeListener in our service allows us to handle this. When audio focus changes we will be notified in the OnAudioFocusChange method. A common implementation of this is below:

It is important to handle Audio Focus to create a great user experience. Even though Android itself does not enforce developers to cooperate in Audio Focus, it is highly encouraged and is what users expect.

Handle AudioBecomingNoisy aka headphones unplugged

Creating a great user experience also means handling some edge cases and stopping audio playback. A very common occurrence is when your users unplug their headphones. Android handles this very differently than anything else we have done yet. You must implement a BroadcastReceiver to handle the AudioManager.ActionAudioBecomingNoisy action. When this is received, we will signal to our background service to stop playing audio using the same method we used to communicate from our user interface.

These are the basics of implementing your very own background audio streaming service. Try this project in Visual Studio, or run this Starter-compatible project in Xamarin Studio on Mac or Windows. I have the full source code example up on GitHub for you to try.

Discuss this blog post in the Xamarin Forums