Building a text to speech app, want it to stop on incoming call, does so in emulator but not phone

Using Visual Studio 2017. As stated, code stops the text to speech function on incoming call in x86 emulator, but not on my nexus 6 running android 7.1.
Here is the code, would appreciate if someone would help. Also if a mod could help me format the code, the code back apostrophes (or grave accents) don't seem to work right.

`using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Speech.Tts;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Telephony;

namespace BHAndroid
{
[Activity(Label = "BHAndroid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity, TextToSpeech.IOnInitListener
{
public static TextToSpeech SpeechText { get; set; }
public static int counter = 0;
public static Boolean Pause = true;
public static TextView TV;
public System.Threading.Tasks.Task BHThread;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button button = FindViewById(Resource.Id.MyButton);
Button button2 = FindViewById(Resource.Id.button1);
TV = FindViewById(Resource.Id.textView1);
SpeechText = new TextToSpeech(this, this);
button.Click += delegate { ButtonStart(); };
button2.Click += delegate { ButtonStop(); };
Intent serviceStart = new Intent(this, typeof(PhoneCallService));
this.StartService(serviceStart);
BHThread = new System.Threading.Tasks.Task(() => { BHThread2(); });
BHThread.Start();
}
public void ButtonStart()
{
Pause = false;
TV.Text = "Started.";
}
public static void ButtonStop ()
{
Pause = true;
TV.Text = "Stopped.";
SpeechText.Stop();
}
public static Boolean stopACK = false;
public void BHThread2()
{
while (true)
{
while (Pause == true)
{
System.Threading.Thread.Sleep(200);
}
String T = "this is a test";
RunOnUiThread(() =>
{
TV.Text = IsServiceRunning();//.ToString();
});
SpeechText.Speak(T, QueueMode.Flush, null,"test");
while (SpeechText.IsSpeaking == true)
{
System.Threading.Thread.Sleep(200);
}
GC.Collect();
}
}
public void OnInit(OperationResult status)
{
if (status.Equals(OperationResult.Success))
{
TV.Text = "Status: Text To Speech Successfully initialized.";
}
else
{
TV.Text = "Status: Text to Speech failed to initialize.";
}
}
private string IsServiceRunning()
{
ActivityManager activityManager = (ActivityManager)GetSystemService(ActivityService);
var serviceInstance = activityManager.GetRunningServices(int.MaxValue).ToList().FirstOrDefault(service => service.Service.ShortClassName.Contains("PhoneCallService"));
return serviceInstance.Service.ClassName;
}
}
public class PhoneCallDetector : PhoneStateListener
{
Context context;
public PhoneCallDetector(Context context_)
{
this.context = context_;
}
public override void OnCallStateChanged(CallState state, string incomingNumber)
{
if (state == CallState.Ringing)
{
//ShowNotification("Incommming call detected from " + incomingNumber);
MainActivity.ButtonStop();
//Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
base.OnCallStateChanged(state, incomingNumber);
}
}
}
[Service]
public class PhoneCallService : Service
{
public override void OnCreate()
{
base.OnCreate();
}
//this will not be called, however it is require to override
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
base.OnStartCommand(intent, flags, startId);
var callDetactor = new PhoneCallDetector(this);
var tm = (TelephonyManager)base.GetSystemService(TelephonyService);
tm.Listen(callDetactor, PhoneStateListenerFlags.CallState);
return StartCommandResult.Sticky;
}
}
[BroadcastReceiver]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class StartupReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Intent serviceStart = new Intent(context, typeof(PhoneCallService));
context.StartService(serviceStart);
}
}
}
`

Tagged:

Answers

  • jamesgentile.9587jamesgentile.9587 USMember
    edited March 2017

    I figured out hooking into call detection is the wrong way to go about this, I ended up using AudioManager.IOnAudioFocusChangeListener to stop the text to speech on incoming call, here's the code if anyone's interested:

    `using System;
    using Android.App;
    using Android.Content;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Android.OS;
    using Android.Speech.Tts;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Android.Telephony;
    using Android.Media;

    namespace BHAndroid
    {
    [Activity(Label = "BHAndroid", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity, TextToSpeech.IOnInitListener, AudioManager.IOnAudioFocusChangeListener
    {
    public static TextToSpeech SpeechText { get; set; }
    public static TextView TV;
    public static AudioManager audioManager;
    protected override void OnCreate(Bundle bundle)
    {
    base.OnCreate(bundle);
    audioManager = (AudioManager)GetSystemService(AudioService);
    SetContentView(Resource.Layout.Main);
    Button button = FindViewById(Resource.Id.MyButton);
    Button button2 = FindViewById(Resource.Id.button1);
    TV = FindViewById(Resource.Id.textView1);
    SpeechText = new TextToSpeech(this, this);
    button.Click += delegate { ButtonStart(); };
    button2.Click += delegate { ButtonStop(); };

        }
        protected override void OnDestroy()
        {
            StopBH();
            TV.Text = "Being destroyed.";
        }
        public static void SpeakBH()
        {
            var p = new Dictionary<string, string>();
            p.Add(TextToSpeech.Engine.KeyParamUtteranceId, "ThisUtterance");
            String T = "this is a test";            
            SpeechText.Speak(T, QueueMode.Flush, p);
        }
        public static void StopBH()
        {            
            SpeechText.Stop();
        }
        public void ButtonStart()
        {            
            StopBH();
            var focusResult = audioManager.RequestAudioFocus(this, Stream.Music, AudioFocus.Gain);
            if (focusResult != AudioFocusRequest.Granted)
            {
                TV.Text = "Audio Focus not granted.";
                return;
            }
            SpeakBH();
            TV.Text = "Started.";
        }                
        public void ButtonStop ()
        {
            StopBH();
            var focusResult = audioManager.RequestAudioFocus(this, Stream.Music, AudioFocus.Loss);
            TV.Text = "Stopped.";            
        }        
        public void OnInit(OperationResult status)
        {
            if (status.Equals(OperationResult.Success))
            {
                TV.Text = "Status: Text To Speech Successfully initialized.";
                SpeechText.SetOnUtteranceProgressListener(new utteranceProgressListener(this));
            }
            else
            {
                TV.Text = "Status: Text to Speech failed to initialize.";
            }            
        }
        public class utteranceProgressListener : UtteranceProgressListener
        {
            MainActivity _parent;
            public utteranceProgressListener(MainActivity p_parent)
            {
                _parent = p_parent;
            }
            public override void OnStart(String utteranceId)
            {
            }
            public override void OnError(String utteranceId)
            {
            }
            public override void OnDone(String utteranceId)
            {
                if (utteranceId != "ThisUtterance")
                {
                    return;
                }
                SpeakBH();
            }
        }
        public void OnAudioFocusChange(AudioFocus focusChange)
        {
            switch (focusChange)
            {
                case AudioFocus.Gain:
                    break;
                case AudioFocus.Loss:
                    //We have lost focus stop!
                    StopBH();
                    TV.Text = "Stop because lost audio focus.";
                    break;
                case AudioFocus.LossTransient:
                    //We have lost focus for a short time, but likely to resume so pause
                    StopBH();
                    TV.Text = "Stop because lost audio focus.";
                    break;
                case AudioFocus.LossTransientCanDuck:
                    //We have lost focus but should till play at a muted 10% volume
                    StopBH();
                    TV.Text = "Stop because lost audio focus.";
                    break;
            }
        }        
    }    
    

    }

    `

Sign In or Register to comment.