Android 语音识别将数据传回 Xamarin Forms
Posted
技术标签:
【中文标题】Android 语音识别将数据传回 Xamarin Forms【英文标题】:Android speech recognition pass data back to Xamarin Forms 【发布时间】:2017-03-29 14:07:56 【问题描述】:我现在真的卡住了,我对 Xamarin 很陌生。 我使用 Xamarin Forms 开发具有语音识别功能的应用程序。
我只创建了一个带有按钮和输入框的简单 UI。
工作:
按下按钮并显示带有语音识别的弹出窗口 将口语读入 var不工作:
将数据传回 Xamarin Forms UI(条目)StartPage.xaml.cs:
private void BtnRecord_OnClicked(object sender, EventArgs e)
WaitForSpeechToText();
private async void WaitForSpeechToText()
EntrySpeech.Text = await DependencyService.Get<Listener.ISpeechToText>().SpeechToTextAsync();
ISpeechToText.cs:
public interface ISpeechToText
Task<string> SpeechToTextAsync();
调用本机代码。
SpeechToText_android.cs:
public class SpeechToText_Android : ISpeechToText
private const int VOICE = 10;
public SpeechToText_Android()
public Task<string> SpeechToTextAsync()
var tcs = new TaskCompletionSource<string>();
try
var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, "Sprechen Sie jetzt");
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
try
((Activity)Forms.Context).StartActivityForResult(voiceIntent, VOICE);
catch (ActivityNotFoundException a)
tcs.SetResult("Device doesn't support speech to text");
catch (Exception ex)
tcs.SetException(ex);
return tcs.Task;
MainActivity.cs:
protected override void OnActivityResult(int requestCode, Result resultVal, Intent data)
if (requestCode == VOICE)
if (resultVal == Result.Ok)
var matches = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
if (matches.Count != 0)
string textInput = matches[0].ToString();
if (textInput.Length > 500)
textInput = textInput.Substring(0, 500);
// RETURN
base.OnActivityResult(requestCode, resultVal, data);
首先我认为我可以通过
return tcs.Task;
回到 ui,但后来我注意到这个返回发生在 语音识别的弹出窗口已完成渲染。这一刻,一句话也没说。
口语在 OnActivityResult 函数中的字符串“textInput”中, 但是我怎样才能将此字符串传递回 Xamarin.Forms UI?
谢谢大家!
【问题讨论】:
SpeechToTextAsync 需要用 async 关键字标记。 【参考方案1】:我会使用 AutoResetEvent
暂停返回,直到调用 OnActivityResult
,直到用户记录某些内容、取消或您在 AutoResetEvent 中超时他们的操作。
从您的 SpeechToTextAsync
方法返回一个 Task<string>
:
public interface ISpeechToText
Task<string> SpeechToTextAsync();
将AutoResetEvent
添加到暂停执行:
注意:包裹AutoResetEvent.WaitOne
以防止挂起应用程序循环
public class SpeechToText_Android : Listener.ISpeechToText
public static AutoResetEvent autoEvent = new AutoResetEvent(false);
public static string SpeechText;
const int VOICE = 10;
public async Task<string> SpeechToTextAsync()
var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, "Sprechen Sie jetzt");
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
SpeechText = "";
autoEvent.Reset();
((Activity)Forms.Context).StartActivityForResult(voiceIntent, VOICE);
await Task.Run(() => autoEvent.WaitOne(new TimeSpan(0, 2, 0)); );
return SpeechText;
MainActivity OnActivityResult:
const int VOICE = 10;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == VOICE)
if (resultCode == Result.Ok)
var matches = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
if (matches.Count != 0)
var textInput = matches[0];
if (textInput.Length > 500)
textInput = textInput.Substring(0, 500);
SpeechToText_Android.SpeechText = textInput;
SpeechToText_Android.autoEvent.Set();
注意:这是使用几个静态变量来简化此示例的实现...有些开发人员会说这是代码异味,我半同意,但您不能拥有多个 Google语音识别器一次运行....
Hello World 示例:
public class App : Application
public App()
var speechTextLabel = new Label
HorizontalTextAlignment = TextAlignment.Center,
Text = "Waiting for text"
;
var speechButton = new Button();
speechButton.Text = "Fetch Speech To Text Results";
speechButton.Clicked += async (object sender, EventArgs e) =>
var speechText = await WaitForSpeechToText();
speechTextLabel.Text = string.IsNullOrEmpty(speechText) ? "Nothing Recorded" : speechText;
;
var content = new ContentPage
Title = "Speech",
Content = new StackLayout
VerticalOptions = LayoutOptions.Center,
Children =
new Label
HorizontalTextAlignment = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
,
speechButton,
speechTextLabel
;
MainPage = new NavigationPage(content);
async Task<string> WaitForSpeechToText()
return await DependencyService.Get<Listener.ISpeechToText>().SpeechToTextAsync();
【讨论】:
非常感谢@SushiHangover!它就像一个魅力。如果我做对了,那么您创建了一个最多等待 2 分钟的线程(autoEvent)。它阻止函数的返回。然后你通过“autoEvent.Set()”发信号通知线程在你得到语音输入后继续,我做对了吗? @user3769192 完全正确,此方法有效,但并不完美....您可能会超时,而当您超时时,您将无法取消 Google 识别器。 “正确”方法是创建一个SpeechRecognizer
(通过SpeechRecognizer.CreateSpeechRecognizer
),构建您自己的用户界面,设置一个RecognitionListener
作为您的回调,从而处理发送到的任何单词您的侦听器在另一个线程中可以取消/停止识别器,在超时或用户取消后,然后拆除您的自定义 UI ....
我尝试了使用 SpeechRecognizer 创建自己的界面的方式,但我认为我失败了。所以我决定回到标准实现。感谢您的解释和您的帮助!
@SushiHangover 我可以与您联系以获取有关此主题的后续问题吗?以上是关于Android 语音识别将数据传回 Xamarin Forms的主要内容,如果未能解决你的问题,请参考以下文章