diff --git a/src/CommunityToolkit.Maui.Core/Essentials/SpeechToText/OfflineSpeechToTextImplementation.android.cs b/src/CommunityToolkit.Maui.Core/Essentials/SpeechToText/OfflineSpeechToTextImplementation.android.cs index 1f4050564..906045aa0 100644 --- a/src/CommunityToolkit.Maui.Core/Essentials/SpeechToText/OfflineSpeechToTextImplementation.android.cs +++ b/src/CommunityToolkit.Maui.Core/Essentials/SpeechToText/OfflineSpeechToTextImplementation.android.cs @@ -57,10 +57,10 @@ static Intent CreateSpeechIntent(SpeechToTextOptions options) return intent; } - static bool IsSpeechRecognitionAvailable() => OperatingSystem.IsAndroidVersionAtLeast(34) && SpeechRecognizer.IsOnDeviceRecognitionAvailable(Application.Context); + static bool IsSpeechRecognitionAvailable() => OperatingSystem.IsAndroidVersionAtLeast(33) && SpeechRecognizer.IsOnDeviceRecognitionAvailable(Application.Context); [MemberNotNull(nameof(speechRecognizer), nameof(listener))] - [SupportedOSPlatform("Android34.0")] + [SupportedOSPlatform("Android33.0")] async Task InternalStartListening(SpeechToTextOptions options, CancellationToken token = default) { if (!IsSpeechRecognitionAvailable()) @@ -81,22 +81,46 @@ async Task InternalStartListening(SpeechToTextOptions options, CancellationToken var recognitionSupportTask = new TaskCompletionSource(); speechRecognizer.CheckRecognitionSupport(recognizerIntent, new Executor(), new RecognitionSupportCallback(recognitionSupportTask)); var recognitionSupportResult = await recognitionSupportTask.Task; + + if (!recognitionSupportResult.SupportedOnDeviceLanguages.Contains(options.Culture.Name)) + { + throw new NotSupportedException($"Culture '{options.Culture.Name}' is not supported"); + } + if (recognitionSupportResult.PendingOnDeviceLanguages.Contains(options.Culture.Name)) + { + throw new Exception($"Speech Recognition {options.Culture.Name} pending download. Loading can be delayed if WiFi only"); + } if (!recognitionSupportResult.InstalledOnDeviceLanguages.Contains(options.Culture.Name)) { - if (!recognitionSupportResult.SupportedOnDeviceLanguages.Contains(options.Culture.Name)) + if (OperatingSystem.IsAndroidVersionAtLeast(34)) { - throw new NotSupportedException($"Culture '{options.Culture.Name}' is not supported"); + await TryDownloadOfflineRecognizer34Async(recognizerIntent, token); + } + else if (OperatingSystem.IsAndroidVersionAtLeast(33)) + { + TryDownloadOfflineRecognizer33(recognizerIntent); } - - var downloadLanguageTask = new TaskCompletionSource(); - speechRecognizer.TriggerModelDownload(recognizerIntent, new Executor(), new ModelDownloadListener(downloadLanguageTask)); - await downloadLanguageTask.Task.WaitAsync(token); } speechRecognizer.SetRecognitionListener(listener); speechRecognizer.StartListening(recognizerIntent); } + [SupportedOSPlatform("Android33.0")] + void TryDownloadOfflineRecognizer33(Intent recognizerIntent) + { + speechRecognizer?.TriggerModelDownload(recognizerIntent); + } + [SupportedOSPlatform("Android34.0")] + async Task TryDownloadOfflineRecognizer34Async(Intent recognizerIntent, CancellationToken token) + { + if (speechRecognizer is not null) + { + var downloadLanguageTask = new TaskCompletionSource(); + speechRecognizer.TriggerModelDownload(recognizerIntent, new Executor(), new ModelDownloadListener(downloadLanguageTask)); + await downloadLanguageTask.Task.WaitAsync(token); + } + } void HandleListenerError(SpeechRecognizerError error) { OnRecognitionResultCompleted(SpeechToTextResult.Failed(new Exception($"Failure in speech engine - {error}"))); @@ -215,6 +239,7 @@ public void OnProgress(int completedPercent) public void OnScheduled() { + downloadLanguageTask.SetException(new Exception($"Speech Recognition pending download. Loading Scheduled WiFi ")); } public void OnSuccess()