Xamarin.Forms
Accesso alle funzionalità native con DependencyService
Ricerca…
Osservazioni
Se non vuoi che il tuo codice si interrompa quando non viene trovata alcuna implementazione, controlla prima DependencyService
se ha un'implementazione disponibile.
Puoi farlo con un semplice controllo se non è null
.
var speaker = DependencyService.Get<ITextToSpeech>();
if (speaker != null)
{
speaker.Speak("Ready for action!");
}
oppure, se il tuo IDE supporta C # 6, con operatore null-condizionale:
var speaker = DependencyService.Get<ITextToSpeech>();
speaker?.Speak("Ready for action!");
Se non lo fai e non viene trovata alcuna implementazione in fase di runtime, il tuo codice genererà un'eccezione.
Implementazione del text-to-speech
Un buon esempio di una funzione che richiede il codice specifico della piattaforma è quando si desidera implementare la sintesi vocale (tts). Questo esempio presuppone che si stia lavorando con codice condiviso in una libreria PCL.
Una panoramica schematica della nostra soluzione apparirebbe come l'immagine sottostante.
Nel nostro codice condiviso definiamo un'interfaccia che è registrata con DependencyService
. Qui è dove faremo le nostre chiamate. Definisci un'interfaccia come sotto.
public interface ITextToSpeech
{
void Speak (string text);
}
Ora in ogni piattaforma specifica, abbiamo bisogno di creare un'implementazione di questa interfaccia. Iniziamo con l'implementazione iOS.
Implementazione 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);
}
}
Nell'esempio di codice sopra riportato si nota che esiste un codice specifico per iOS. Ti piace tipi come AVSpeechSynthesizer
. Questi non funzionerebbero nel codice condiviso.
Per registrare questa implementazione con Xamarin DependencyService
aggiungere questo attributo sopra la dichiarazione dello spazio dei nomi.
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
Ora quando fai una chiamata come questa nel tuo codice condiviso, viene iniettata l'implementazione corretta per la piattaforma su cui stai eseguendo la tua app.
DependencyService.Get<ITextToSpeech>()
. Maggiori informazioni su questo in seguito.
Implementazione Android
L'implementazione di Android di questo codice potrebbe apparire come sotto.
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
}
Ancora una volta non dimenticare di registrarlo con 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
Implementazione di Windows Phone
Infine, per Windows Phone è possibile utilizzare questo codice.
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);
}
}
E ancora una volta non dimenticare di registrarlo.
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
Implementazione in codice condiviso
Ora è tutto a posto per farlo funzionare! Infine, nel tuo codice condiviso ora puoi chiamare questa funzione usando l'interfaccia. In fase di esecuzione verrà iniettata l'implementazione che corrisponde alla piattaforma corrente su cui è in esecuzione.
In questo codice vedrai una pagina che potrebbe essere in un progetto Xamarin Forms. Crea un pulsante che richiama il metodo Speak()
utilizzando DependencyService
.
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;
}
Il risultato sarà che quando l'app viene eseguita e si fa clic sul pulsante, verrà pronunciato il testo fornito.
Tutto questo senza dover fare cose difficili come suggerimenti per il compilatore e così via. Ora hai un modo uniforme per accedere alle funzionalità specifiche della piattaforma attraverso un codice indipendente dalla piattaforma.
Ottenere numeri di versione del sistema operativo dell'applicazione e del dispositivo - Android e iOS - PCL
L'esempio seguente raccoglierà il numero di versione del sistema operativo del dispositivo e la versione dell'applicazione (definita nelle proprietà di ciascun progetto) immessa nel nome della versione su Android e versione su iOS.
Per prima cosa crea un'interfaccia nel tuo progetto PCL:
public interface INativeHelper {
/// <summary>
/// On iOS, gets the <c>CFBundleVersion</c> number and on Android, gets the <c>PackageInfo</c>'s <c>VersionName</c>, both of which are specified in their respective project properties.
/// </summary>
/// <returns><c>string</c>, containing the build number.</returns>
string GetAppVersion();
/// <summary>
/// On iOS, gets the <c>UIDevice.CurrentDevice.SystemVersion</c> number and on Android, gets the <c>Build.VERSION.Release</c>.
/// </summary>
/// <returns><c>string</c>, containing the OS version number.</returns>
string GetOsVersion();
}
Ora implementiamo l'interfaccia nei progetti Android e iOS.
Android:
[assembly: Dependency(typeof(NativeHelper_Android))]
namespace YourNamespace.Droid{
public class NativeHelper_Android : INativeHelper {
/// <summary>
/// See interface summary.
/// </summary>
public string GetAppVersion() {
Context context = Forms.Context;
return context.PackageManager.GetPackageInfo(context.PackageName, 0).VersionName;
}
/// <summary>
/// See interface summary.
/// </summary>
public string GetOsVersion() { return Build.VERSION.Release; }
}
}
iOS:
[assembly: Dependency(typeof(NativeHelper_iOS))]
namespace YourNamespace.iOS {
public class NativeHelper_iOS : INativeHelper {
/// <summary>
/// See interface summary.
/// </summary>
public string GetAppVersion() { return Foundation.NSBundle.MainBundle.InfoDictionary[new Foundation.NSString("CFBundleVersion")].ToString(); }
/// <summary>
/// See interface summary.
/// </summary>
public string GetOsVersion() { return UIDevice.CurrentDevice.SystemVersion; }
}
}
Ora per usare il codice in un metodo:
public string GetOsAndAppVersion {
INativeHelper helper = DependencyService.Get<INativeHelper>();
if(helper != null) {
string osVersion = helper.GetOsVersion();
string appVersion = helper.GetBuildNumber()
}
}