Xamarin.Forms
Toegang tot native functies met DependencyService
Zoeken…
Opmerkingen
Als u niet wilt dat uw code breekt wanneer er geen implementatie wordt gevonden, controleer dan eerst de DependencyService
als er een implementatie beschikbaar is.
U kunt dit doen door een eenvoudige controle als het niet null
.
var speaker = DependencyService.Get<ITextToSpeech>();
if (speaker != null)
{
speaker.Speak("Ready for action!");
}
of, als uw IDE C # 6 ondersteunt, met null-voorwaardelijke operator:
var speaker = DependencyService.Get<ITextToSpeech>();
speaker?.Speak("Ready for action!");
Als u dit niet doet en er tijdens de uitvoering geen implementatie wordt gevonden, genereert uw code een uitzondering.
Tekst-naar-spraak implementeren
Een goed voorbeeld van een functie die platformspecifieke code aanvraagt, is wanneer u tekst-naar-spraak (tts) wilt implementeren. In dit voorbeeld wordt ervan uitgegaan dat u met gedeelde code in een PCL-bibliotheek werkt.
Een schematisch overzicht van onze oplossing lijkt op de afbeelding hieronder.
In onze gedeelde code definiëren we een interface die is geregistreerd bij de DependencyService
. Dit is waar we onze oproepen zullen doen. Definieer een interface zoals hieronder.
public interface ITextToSpeech
{
void Speak (string text);
}
Nu moeten we in elk specifiek platform een implementatie van deze interface maken. Laten we beginnen met de iOS-implementatie.
iOS-implementatie
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);
}
}
In het bovenstaande codevoorbeeld merk je dat er specifieke code is voor iOS. Zoals types zoals AVSpeechSynthesizer
. Deze zouden niet werken in gedeelde code.
Als u deze implementatie bij de Xamarin DependencyService
wilt registreren, voegt u dit kenmerk toe boven de naamruimteaangifte.
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
Wanneer u nu een dergelijke oproep doet in uw gedeelde code, wordt de juiste implementatie voor het platform waarop u uw app uitvoert geïnjecteerd.
DependencyService.Get<ITextToSpeech>()
. Hierover later meer.
Android-implementatie
De Android-implementatie van deze code ziet er hieronder uit.
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
}
Vergeet opnieuw niet om het te registreren bij de 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-implementatie
Ten slotte kan deze code voor Windows Phone worden gebruikt.
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);
}
}
En vergeet niet opnieuw om het te registreren.
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
Implementeren in gedeelde code
Nu is alles aanwezig om het te laten werken! Ten slotte kunt u in uw gedeelde code deze functie nu aanroepen via de interface. Tijdens runtime wordt de implementatie geïnjecteerd die overeenkomt met het huidige platform waarop deze wordt uitgevoerd.
In deze code ziet u een pagina die mogelijk deel uitmaakt van een Xamarin Forms-project. Het maakt een knop die de methode Speak()
aanroept met behulp van de 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;
}
Het resultaat is dat wanneer de app wordt uitgevoerd en op de knop wordt geklikt, de verstrekte tekst wordt uitgesproken.
Dit alles zonder harde dingen te hoeven doen, zoals compilerhints en dergelijke. U hebt nu een uniforme manier om toegang te krijgen tot platformspecifieke functionaliteit via platformonafhankelijke code.
Versienummer van toepassing en apparaat-besturingssysteem verkrijgen - Android en iOS - PCL
Het onderstaande voorbeeld verzamelt het OS-versienummer van het apparaat en de versie van de applicatie (die is gedefinieerd in de eigenschappen van elk project) die is ingevoerd in de versienaam op Android en de versie op iOS.
Maak eerst een interface in uw PCL-project:
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();
}
Nu implementeren we de interface in de Android- en iOS-projecten.
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; }
}
}
Om de code nu in een methode te gebruiken:
public string GetOsAndAppVersion {
INativeHelper helper = DependencyService.Get<INativeHelper>();
if(helper != null) {
string osVersion = helper.GetOsVersion();
string appVersion = helper.GetBuildNumber()
}
}