實施文字轉語音

當你想要實現文字到語音轉換(tts)時,請求特定於平臺的程式碼的功能的一個很好的示例。此示例假定你正在使用 PCL 庫中的共享程式碼。

我們的解決方案的示意圖將看起來像下面的影象。

StackOverflow 文件

在我們的共享程式碼中,我們定義了一個在 DependencyService 中註冊的介面。這是我們呼叫的地方。定義類似於下面的介面。

public interface ITextToSpeech
{
    void Speak (string text);
}

現在,在每個特定平臺中,我們需要建立此介面的實現。讓我們從 iOS 實現開始。

iOS 實施

using AVFoundation;

public class TextToSpeechImplementation : ITextToSpeech
{
    public TextToSpeechImplementation () {}

    public void Speak (string text)
    {
        var speechSynthesizer = new AVSpeechSynthesizer ();

        var speechUtterance = new AVSpeechUtterance (text) {
            Rate = AVSpeechUtterance.MaximumSpeechRate/4,
            Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
            Volume = 0.5f,
            PitchMultiplier = 1.0f
        };

        speechSynthesizer.SpeakUtterance (speechUtterance);
    }
}

在上面的程式碼示例中,你注意到 iOS 有特定的程式碼。像 AVSpeechSynthesizer 這樣的型別。這些在共享程式碼中不起作用。

要使用 Xamarin DependencyService 註冊此實現,請在名稱空間宣告上方新增此屬性。

using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace

[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS {
    public class TextToSpeechImplementation : ITextToSpeech
//... Rest of code

現在,當你在共享程式碼中執行此類呼叫時,將注入正在執行應用程式的平臺的正確實現。

DependencyService.Get<ITextToSpeech>()。稍後會詳細介紹。

Android 實施

這段程式碼的 Android 實現看起來就像在下面。

using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;

public class TextToSpeechImplementation : Java.Lang.Object, ITextToSpeech, TextToSpeech.IOnInitListener
{
    TextToSpeech speaker;
    string toSpeak;

    public TextToSpeechImplementation () {}

    public void Speak (string text)
    {
        var ctx = Forms.Context; // useful for many Android SDK features
        toSpeak = text;
        if (speaker == null) {
            speaker = new TextToSpeech (ctx, this);
        } else {
            var p = new Dictionary<string,string> ();
            speaker.Speak (toSpeak, 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
}

再次不要忘記將其註冊到 DependencyService

using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;

[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.Droid{
    //... Rest of code

Windows Phone 實現

最後,對於 Windows Phone,可以使用此程式碼。

public class TextToSpeechImplementation : ITextToSpeech
{
    public TextToSpeechImplementation() {}

    public async void Speak(string text)
    {
        MediaElement mediaElement = new MediaElement();

        var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();

        SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Hello World");

        mediaElement.SetSource(stream, stream.ContentType);
        mediaElement.Play();
        await synth.SynthesizeTextToStreamAsync(text);
    }
}

再一次不要忘記註冊它。

using Windows.Media.SpeechSynthesis;
using Windows.UI.Xaml.Controls;
using DependencyServiceSample.WinPhone;//enables registration outside of namespace

[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.WinPhone{
    //... Rest of code

在共享程式碼中實現

現在一切都準備好了! 最後,在共享程式碼中,你現在可以使用該介面呼叫此函式。在執行時,將注入與其執行的當前平臺相對應的實現。

在此程式碼中,你將看到可能位於 Xamarin Forms 專案中的頁面。它建立了一個按鈕,通過使用 DependencyService 呼叫 Speak() 方法。

public MainPage ()
{
    var speak = new Button {
        Text = "Hello, Forms !",
        VerticalOptions = LayoutOptions.CenterAndExpand,
        HorizontalOptions = LayoutOptions.CenterAndExpand,
    };
    speak.Clicked += (sender, e) => {
        DependencyService.Get<ITextToSpeech>().Speak("Hello from Xamarin Forms");
    };
    Content = speak;
}

結果是當應用程式執行並單擊按鈕時,將說出提供的文字。

所有這一切都無需像編譯器提示等那樣做。你現在可以通過獨立於平臺的程式碼來統一訪問平臺特定功能。