Carlos Rodrigez Carlos Rodrigez - 10 days ago 5
C# Question

How can I return the value from my Task<string> in my iOS Dependecy Service [Xamarin.Forms.iOS]?

I am running a function that works correctly and I get the correct value but I am having issues figuring out how I can get the value (that is a string with text)from my DI Service back to my shared code. When I type the result out in the log in the function below I get the correct value:

RecognitionTask = SpeechRecognizer.GetRecognitionTask (LiveSpeechRequest, (SFSpeechRecognitionResult result, NSError err) =>
{
thetextresult = result.BestTranscription.FormattedString;
System.Diagnostics.Debug.WriteLine(thetextresult); //I get the correct value
});


(If I await this code above can that solve my problem maybe?, if so how can i await a result from a string?)

My current problem is that after this code I work with the log once again to see if I can reach the log again after this function:

System.Diagnostics.Debug.WriteLine("Do I reach this?");


But I cannot reach this so the
return thetextresult
in the end of the function does not get reached which means that I do not get value in return in my shared code.

This is how the code looks:

Function in my iOS DependecyService:

[assembly: Xamarin.Forms.Dependency(typeof(SpeechToText_iOS))]
namespace myProject.iOS
{
public class SpeechToText_iOS : ISoundToSpeak
{

public SpeechToText_iOS() {}

AVAudioEngine AudioEngine = new AVAudioEngine();
SFSpeechAudioBufferRecognitionRequest LiveSpeechRequest = new SFSpeechAudioBufferRecognitionRequest();
SFSpeechRecognitionTask RecognitionTask;
SFSpeechRecognizer SpeechRecognizer = new SFSpeechRecognizer();

string thetextresult = "";
public async Task<string> SpeechToTextAsync ()
{
if (SFSpeechRecognizer.AuthorizationStatus != SFSpeechRecognizerAuthorizationStatus.Authorized)
{

SFSpeechRecognizer.RequestAuthorization((SFSpeechRecognizerAuthorizationStatus status) =>
{
switch (status)
{
case SFSpeechRecognizerAuthorizationStatus.Authorized:

break;

case SFSpeechRecognizerAuthorizationStatus.Denied:

break;

case SFSpeechRecognizerAuthorizationStatus.NotDetermined:

break;

case SFSpeechRecognizerAuthorizationStatus.Restricted:

break;
}
});

}

else {

var node = AudioEngine.InputNode;
var recordingFormat = node.GetBusOutputFormat(0);

node.InstallTapOnBus(0, 1024, recordingFormat, (AVAudioPcmBuffer buffer, AVAudioTime when) =>
{
LiveSpeechRequest.Append(buffer);
});

AudioEngine.Prepare();
NSError error;
AudioEngine.StartAndReturnError(out error);

RecognitionTask = SpeechRecognizer.GetRecognitionTask (LiveSpeechRequest, (SFSpeechRecognitionResult result, NSError err) =>
{
thetextresult = result.BestTranscription.FormattedString;
System.Diagnostics.Debug.WriteLine(thetextresult); //value gets out correctly.
});


}

System.Diagnostics.Debug.WriteLine("Do I reach this?"); //this does not get reached when i do the function.
return thetextresult; //which means that this is not returning the value
}


Interface:

public interface ISoundToSpeak
{
Task<string> SpeechToTextAsync();
}


How i use it on my contentpage, function:

async Task <string>WaitForSpeech()
{
return await DependencyService.Get<ISoundToSpeak>().SpeechToTextAsync();
}


a button:

async void speakClick(object s, EventArgs a)
{
var speechText = await WaitForSpeech();
System.Diagnostics.Debug.WriteLine(speechText); //so with this current code i do not get the text out in my shared code.
}

Answer

Your function StartRecord is async but I don't see any await inside it. SpeechRecognizer.GetRecognitionTask is a task with callback. You should be able to reach "Do I reach this?" but the result of thetextresult is not going to be there as you don't wait till GetRecognitionTask completes. You should either await somehow on RecognitionTask or not return textresult from a function but call your shared code from callback.

What worked at the end is providing a callback function to SpeechToTextAsync.