DependencyService
Remarks#
When using DependencyService
you typically need 3 parts:
- Interface - This defines the functions you wish to abstract.
- Platform implementation - A class within each platform specific project that implements the previously defined interface.
- Registration - Each platform specific implementation class has to be registered with the
DependencyService
through a metadata attribute. This enables theDependencyService
to find your implementation at run time.
When using DependencyService
you are required to provide an implementation for each platform you target. When an implementation is not provided the application will fail at run time.
Interface
The interface defines the behaviour that you want to expose through the DependencyService
. One example usage of a DependencyService
is a Text-To-Speech service. There is currently no abstraction for this feature in Xamarin.Forms, so you need to create your own. Start off by defining an interface for the behaviour:
public interface ITextToSpeech
{
void Speak (string whatToSay);
}
Because we define our interface we can code against it from our shared code.
Note: Classes that implement the interface need to have a parameterless constructor to work with the DependencyService
.
iOS implementation
The interface you defined needs to be implemented in every targeted platform. For iOS this is done through the AVFoundation
framework. The following implementation of the ITextToSpeech
interface handles speaking a given text in English.
using AVFoundation;
public class TextToSpeechiOS : ITextToSpeech
{
public TextToSpeechiOS () {}
public void Speak (string whatToSay)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
var speechUtterance = new AVSpeechUtterance (whatToSay) {
Rate = AVSpeechUtterance.MaximumSpeechRate/4,
Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
Volume = 0.5f,
PitchMultiplier = 1.0f
};
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
When you’ve created your class you need to enable the DependencyService
to discover it at run time. This is done by adding an [assembly]
attribute above the class definition and outside of any namespace definitions.
using AVFoundation;
using DependencyServiceSample.iOS;
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechiOS))]
namespace DependencyServiceSample.iOS {
public class TextToSpeechiOS : ITextToSpeech
...
This attribute registers the class with the DependencyService
so it can be used when an instance of the ITextToSpeech
interface is needed.
Shared code
After you’ve created and registered your platform-specific classes you can start hooking them up to your shared code. The following page contains a button that triggers the text-to-speech functionality using a pre-defined sentence. It uses DependencyService
to retrieve a platform-specific implementation of ITextToSpeech
at run time using the native SDKs.
public MainPage ()
{
var speakButton = new Button {
Text = "Talk to me baby!",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
speakButton.Clicked += (sender, e) => {
DependencyService.Get<ITextToSpeech>().Speak("Xamarin Forms likes eating cake by the ocean.");
};
Content = speakButton;
}
When you run this application on an iOS or Android device and tap the button you will hear the application speak the given sentence.
Android implementation
The Android specific implementation is a bit more complex because it forces you to inherit from a native Java.Lang.Object
and forces you to implement the IOnInitListener
interface. Android requires you to provide a valid Android context for a lot of the SDK methods it exposes. Xamarin.Forms exposes a Forms.Context
object that provides you with a Android context that you can use in such cases.
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
public class TextToSpeechAndroid : Java.Lang.Object, ITextToSpeech, TextToSpeech.IOnInitListener
{
TextToSpeech _speaker;
public TextToSpeechAndroid () {}
public void Speak (string whatToSay)
{
var ctx = Forms.Context;
if (_speaker == null)
{
_speaker = new TextToSpeech (ctx, this);
}
else
{
var p = new Dictionary<string,string> ();
_speaker.Speak (whatToSay, QueueMode.Flush, p);
}
}
#region IOnInitListener implementation
public void OnInit (OperationResult status)
{
if (status.Equals (OperationResult.Success))
{
var p = new Dictionary<string,string> ();
_speaker.Speak (toSpeak, QueueMode.Flush, p);
}
}
#endregion
}
When you’ve created your class you need to enable the DependencyService
to discover it at run time. This is done by adding an [assembly]
attribute above the class definition and outside of any namespace definitions.
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechAndroid))]
namespace DependencyServiceSample.Droid {
...
This attribute registers the class with the DependencyService
so it can be used when an instance of the ITextToSpeech
interface is needed.