Recently I was chatting with a Microsoft MVP who is actively working in mobile development and also with Xamarin. I was trying to create a music player with one button to start playing music or stop it. When you are using Xamarin Forms, you need to use a dependency service to use native code to play music on each platform. Now the issue here is, how do I do this? There isn’t any documentation anywhere.

The trick is to use an action delegate to pass a method as a parameter when calling your dependency service method. How this exactly works will be explained below.

First of all let’s create a new Xamarin Forms project or use your own project.

Create a folder ‘Services’, and create an interface ‘IAudioService’.

using System;

namespace RGR_FM.Services
{
    public interface IAudioService
    {
        void Play(Action<bool> isPlaying);
        void Stop(Action<bool> isPlaying);
        bool IsPlaying();
    }
}

Now you can choose, either in your Android, iOS or UWP project, create a ‘Services’ folder. In my example I will use Android.

Now in the ‘Services folder’ of the platform of your preference, create a class ‘AudioService’. Make sure it inherits from the interface ‘IAudioService’.

using System;
using Android.Content;
using Android.Media;
using Java.IO;
using RGR_FM.Droid.Services;
using RGR_FM.Services;
using Xamarin.Forms;

[assembly: Dependency(typeof(AudioService))]
namespace RGR_FM.Droid.Services
{
    public class AudioService : IAudioService
    {
        private MediaPlayer _mediaPlayer;
        private Action<bool> _isPlaying;

          public AudioService()
           {
           }

        public void Play(Action<bool> isPlaying)
        {
            // If you are missing this you will get a NullPointerException. This is necessary!
            _isPlaying = isPlaying;
               _mediaPlayer = new MediaPlayer();
               _mediaPlayer.SetDataSource("http://stream.intronic.nl/rgrfm");
               _mediaPlayer.SetAudioStreamType(Stream.Music);
               _mediaPlayer.Prepared += MediaPlayerPrepared;
               _mediaPlayer.Error += MediaPlayerError;
               try
               {
                   _mediaPlayer.Prepare();
               }
               catch (IOException e)
               {
                   // prepare failed, no internet connection, notify the UI
                   _isPlaying(false);
               }
           }

           public void Stop(Action<bool> isPlaying)
           {
            // If you are missing this you will get a NullPointerException. This is necessary!
               _isPlaying = isPlaying;
               _mediaPlayer.Stop();

            // Notify the UI
            _isPlaying(false);
        }

        public bool IsPlaying()
        {
            if (_mediaPlayer != null)
                return _mediaPlayer.IsPlaying;
            return false;
        }

        // Fired when an error has occurred during playback
        private void MediaPlayerError(object sender, MediaPlayer.ErrorEventArgs e)
        {
            // handle error

            // Notify the UI, and update UI accordingly
            _isPlaying(false);
        }

        // Fired when the MediaPlayer is ready to play.
        private void MediaPlayerPrepared(object sender, EventArgs e)
        {
            _mediaPlayer.Start();

                // Notify the UI playback started.
                _isPlaying(true);
        }
    }
}

Assuming you use XAML for your pages, add a button called ‘ButtonPlay’ and set as text ‘Play’:

<Button x:Name="ButtonPlay" Text="Play" />

Now in the code behind, in the constructor you could put something like:

ButtonPlay.Command = new Command(() =>
{
    if (DependencyService.Get<IAudioService>().IsPlaying())
    {
        DependencyService.Get<IAudioService>().Stop(isPlaying =>
        {
            ButtonPlay.Text = "Play";
        });
    }
    else
    {
        DependencyService.Get<IAudioService>().Play(isPlaying =>
        {
            // If isPlaying is equal to false, it means we didn't have any internet connection and streaming music would fail.
            if (isPlaying)
            {
                ButtonPlay.Text = "Stop";
            }
            else
            {
                ButtonPlay.Text = "Play";
            }
        });
    }
});