TextToSpeech cannot be stopped correctly

1k Views Asked by At

I have a text that is refreshed, and every time this happens.

I call a static method method speak() located in another class with this structure:

public class Voc {

    static TextToSpeech mytts;

    public static void speak(String myText){
       mytts=new TextToSpeech(c, new TextToSpeech.OnInitListener() {
        //.........parameters and config not related to issue........
       }
       mytts.speak();
    }

    public static off(){
       mytts.stop();
       mytts.shutdown();
    }

}

The problem is that if I call off() after multiple speak() invocations, the tts continues to speak. This doesn't happens if I invoke speak() only a single time and not multiple time as happens in the refresh method. This raise me the suspect that off() method doesn't work for all instances despite I have assigned all the new TextToSpeech(...) invocations to same static field in the class Voc.

How could I fix this issue?

1

There are 1 best solutions below

11
ViaTech On

Your issue is due to the fact that you instantiate a new TextToSpeech object on each call of speak(), this is not needed. With the updates I provided below, you have a single TTS object that you turn off and back on, not multiple so when you turn it off the single TTS object is stopped and your issue is no longer present.

I have tested this on my phone and it should work exactly as you need.

Please check my updated code below:

Updated Voc Class

import android.content.Context;
import android.os.Build;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import java.util.Locale;

public class Voc {

    static TextToSpeech mytts = null;

    public static void init(Context c){
        mytts=new TextToSpeech(c, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if(status == TextToSpeech.SUCCESS){
                    int result=mytts.setLanguage(Locale.US);
                    if(result==TextToSpeech.LANG_NOT_SUPPORTED ||
                            result==TextToSpeech.LANG_MISSING_DATA){
                        Log.d("error", "Language not supported");
                    }
                } else
                    Log.d("error", "TTS failed :(");
            }
        });
    }

    public static void speak(final String myText){  
        if(mytts != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mytts.speak(myText, TextToSpeech.QUEUE_FLUSH, null, null);
            } else {
                //cover all versions...
                mytts.speak(myText, TextToSpeech.QUEUE_FLUSH, null);
            }
        }
    }

   public static void off(){
        if(mytts !=null) {
            mytts.stop();
            //mytts.shutdown();  //calling this here is not what we want
        }
   }

   public static void shutdown(){
        if(mytts !=null) {
            mytts.shutdown();  //if you need call shutdown with this method
        }
   }
}

Main Activity For Test

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Voc.init(getApplicationContext()); //this is the method that sets everything up

        Button onButton = (Button) findViewById(R.id.button_on);
        onButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Voc.speak("blah blah blah blah blah blah blah blah");

            }
        });

        Button offButton = (Button) findViewById(R.id.button_off);
        offButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Voc.off();
            }
        });
    }
}

Example Layout For Test

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.viatechsystems.tts.MainActivity">

<Button
    android:id="@+id/button_on"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click me for TTS"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintHorizontal_bias="0.292"
    app:layout_constraintVertical_bias="0.498" />

<Button
    android:id="@+id/button_off"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Off"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="@+id/button_on"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintHorizontal_bias="0.75"
    app:layout_constraintVertical_bias="0.498" />

</android.support.constraint.ConstraintLayout>