0

I've been trying to add speech-to-text to my android app but i'm keep getting "Android.Content.ActivityNotFoundAcception".
I'm using android 5.0 (lollipop) emulator since my computer can't start any other emulator.

Interface:

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

Creating intent and starting activity:

    // When i remove Java.Lang.Object it gives Java.Lang.NullPointer Exception 
    public class AndroidSpeech : Java.Lang.Object, ISpeech
    {
        public static AutoResetEvent autoEvent = new AutoResetEvent(false);
        private Intent voiceIntent;
        public static readonly int speech = 10; // requestCode
        public static string speechResults;
        public async Task<string> SpeechToTextAsync()
        {
            var context = Forms.Context;
            var activity = (Activity)context;
            voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
            voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
            voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, "Speak");
            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);
            autoEvent.Reset();
            activity.StartActivityForResult(voiceIntent, speech);
            await Task.Run(() => { autoEvent.WaitOne(new TimeSpan(0, 0, 3)); });
            return speechResults;
        }
    }

It works fine until getting OnActivityResult, here it throwes the exception
Main Activity:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    if (requestCode == AndroidSpeech.speech)
    {
       // resultCode returns Result.Canceled
       if (resultCode == Result.Ok) // here it throws ActivityNotFoundException
       {
          var speech = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
          AndroidSpeech.speechResults = speech[0];
       }
       AndroidSpeech.autoEvent.Set();
    }
    base.OnActivityResult(requestCode, resultCode, data);
}

Calling function on button click:

 private async void OnStartBtnClick(object sender, EventArgs args)
 {
      string speechResults = await DependencyService.Get<ISpeech().SpeechToTextAsync();
      Lbl.Text = speechResults;
 }

I also tried:

    [Activity]
    public class AndroidSpeech : Activity, ISpeech
    {
        // this gives Java.Lang.NullPointer Exception 
    }

And i also tried creating my own RecognitionListener but i can't return the results.

ozgur
  • 1
  • 1

1 Answers1

1

If you get the "Android.Content.ActivityNotFoundAcception". Because xamarin Dependencyservice just have on activity, and AndroidSpeech is not a activity, you do not use StartActivityForResult directly.Solution is to get a reference to the current activity, in order to do that we are going to add one nuget called Plugin.Current activity

You can add the activity callbacks in our Application class, so my application class looks like this

  [Application]
public class MainApplication : Application, Application.IActivityLifecycleCallbacks
{
    public MainApplication(IntPtr handle, JniHandleOwnership transer)
      : base(handle, transer)
    {
    }

    public override void OnCreate()
    {
        base.OnCreate();
        RegisterActivityLifecycleCallbacks(this);
        //A great place to initialize Xamarin.Insights and Dependency Services!
    }

    public override void OnTerminate()
    {
        base.OnTerminate();
        UnregisterActivityLifecycleCallbacks(this);
    }

    public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
    {
        CrossCurrentActivity.Current.Activity = activity;
    }

    public void OnActivityDestroyed(Activity activity)
    {
    }

    public void OnActivityPaused(Activity activity)
    {
    }

    public void OnActivityResumed(Activity activity)
    {
        CrossCurrentActivity.Current.Activity = activity;
    }

    public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
    {
    }

    public void OnActivityStarted(Activity activity)
    {
        CrossCurrentActivity.Current.Activity = activity;
    }

    public void OnActivityStopped(Activity activity)
    {
    }
}

And in AndroidSpeech class you get the reference to the current activity like this

_activity = CrossCurrentActivity.Current.Activity;

Then you can call StartActivityForResult in AndroidSpeech

There is Blog about how to achieved speech-to-text step by step, you could refer to it. https://medium.com/@dev.aritradas/xamarin-forms-speech-recognition-c16f07cdf164

and this is demo. https://github.com/dev-aritra/XFSpeech

update This is running GIF.

enter image description here

Leon
  • 8,404
  • 2
  • 9
  • 52
  • If the reply is helpful, please try to mark it as an answer( please click the “✔” at the right of answer). It will help others who have similar issue. – Leon Mar 29 '19 at 08:50
  • Target of StartActivityForResult is null (NullReferenceException) i get this, "CrossCurrentActivity.Current.Activity" returns null. – ozgur Mar 30 '19 at 13:52
  • Okay now i can start speech recognizer using "((Activity)Forms.Context)" but after speech ends speechResults returns null (it never calls "OnActivityResult"). – ozgur Mar 30 '19 at 15:13
  • I test this code in my pixel, code :https://github.com/851265601/SpeechToTextDemo. You should run this code in android device, not run it in your android emulator. – Leon Mar 31 '19 at 03:59
  • I tried your code with two different phones but still can't return speech results. – ozgur Apr 01 '19 at 12:41
  • I update my running GIF, you could see that in answer, I updated it , that is worked, Do your phones meet these requirements? 1.Phones need install `google play service`,2.Connect to the network(it could access Google). You also could upload your code, i will test it for you in pixel to exclude problems of phones. – Leon Apr 02 '19 at 02:12
  • Are there any updates for this issue? If the reply is helpful, please try to mark it as an answer, it will help others who have similar issue. – Leon Apr 04 '19 at 01:17