I'm trying to get the activity to finish after it's finished speaking but for some reason I cannot fathom it tells me that the setOnUtteranceCompleted not applicable for text to speech. I'm new to android programming so please be gentle :-)
Here's the code...
public class SpeakActivity extends Activity implements OnUtteranceCompletedListener{
Random randnum = new Random();
TextToSpeech tts = null;
private boolean ttsIsInit = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_speak);
// Show the Up button in the action bar.
setupActionBar();
startTextToSpeech();
}
void startTextToSpeech(){
final int randint = randnum.nextInt(4);
final String text = ((GlobVars) this.getApplication()).getResponse(randint);
tts = new TextToSpeech(this, new OnInitListener() {
public void onInit(int status) {
tts.setOnUtteranceCompletedListener(this);
if (status == TextToSpeech.SUCCESS) {
ttsIsInit = true;
if (tts.isLanguageAvailable(Locale.ENGLISH) >= 0){
tts.setLanguage(Locale.ENGLISH);
}
tts.setPitch(0.5f);
tts.setSpeechRate(0.5f);
if (tts != null && ttsIsInit) {
Log.d("got ere", "spoken");
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
}
}
}
});
}
// shut down tts to free the TTS resources
#Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
public void onUtteranceCompleted(String arg0) {
((GlobVars) this.getApplication()).setListen(true);
this.finish();
}
}
I am ot sure but as per the docs of setOnUtteranceCompletedListener(), you might need to use TextToSpeech.OnUtteranceCompletedListener listener as an argument. I think the way to use the function is as below. Note that use runOnUIThread method in case you want to make any changes to the UI on the call of the onUtteranceCompleted function.
TextToSpeech tts= new TextToSpeech(context, new OnInitListener() {
#Override
public void onInit(int status) {
tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
#Override
public void onUtteranceCompleted(String utteranceId) {
//Do things here
}
});
}
});
Source of above : Check onUtteranceCompleted does not get called? question.
Hope this helps.
Related
I'm using Android Studio. Code java.I want to make TextToSpeech language Turkish.How can I make the voice Turkish?
my code:
TextToSpeech textToSpeech ;
ImageView ımagespeech;
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int i) {
if (i !=TextToSpeech.ERROR){
textToSpeech.setLanguage(new Locale("en_US"));
textToSpeech.setSpeechRate((float)1.0);
}
}
});
ımagespeech.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String gettext =tvtcontextt.getText().toString();
textToSpeech.speak(gettext,TextToSpeech.QUEUE_FLUSH,null);
}
});
#Override
protected void onPause() {
if (textToSpeech != null ){
textToSpeech.stop();
textToSpeech.shutdown();
}
super.onPause();
}
I recently discovered this languages. The speech quality looks promising on the web app.
Give it a shot :)
this is my solution,
in this way the code selects the language used in the device:
private TextToSpeech tts;
#Override
public void onResume() {
super.onResume();
//((AppCompatActivity) getActivity()).getSupportActionBar().hide();
tts = new TextToSpeech(requireContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
//int result = tts.setLanguage(Locale.forLanguageTag("en-US"));
int result = tts.setLanguage(Locale.forLanguageTag(Locale.getDefault().toLanguageTag()));
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "The Language not supported!");
} else {
Log.d("TTS", "TTS its working");
}
}
}
});
}
// in your code
tts.speak("read this", TextToSpeech.QUEUE_FLUSH, null, "");
#Override
public void onPause() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onPause();
}
This is a test activity when the button is pressed the textToSpeech works just fine, but it wont work when the function playString() is called, playString() is being called from the onCreate() of this TestActivity.
public class TestActivity extends Activity {
TextToSpeech textToSpeech;
EditText editText;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
editText=(EditText)findViewById(R.id.editText);
button=(Button)findViewById(R.id.button);
textToSpeech=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
});
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
});
playString();
}
public void playString(){
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
public void onPause(){
if(textToSpeech !=null){
textToSpeech.stop();
textToSpeech.shutdown();
}
super.onPause();
}
}
From documentation:
TextToSpeech instance can only be used to synthesize text once it has completed its initialization.
Initialization may take long time (on my device it's take ~30 seconds), so you can't use handler with some random delay.
Instead, you can place playString() in onInit block right after textToSpeech.setLanguage(Locale.UK);, so string will be played when it can be played.
Please use below code in oncreate method to call the texttospeech:
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
});
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
}, 500);
I want to Convert some text to Speech during oncreate method.
That is when the activity starts it will speak some text.
How can i do that???
I know how to work normally with tts.
These are sample code. But it doesn't work when the activity starts.
public class AndroidTextToSpeechActivity extends Activity implements
TextToSpeech.OnInitListener {
/** Called when the activity is first created. */
private TextToSpeech tts;
private Button btnSpeak;
private EditText txtText;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tts = new TextToSpeech(this, this);
btnSpeak = (Button) findViewById(R.id.btnSpeak);
txtText = (EditText) findViewById(R.id.txtText);
// button on click event
btnSpeak.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
speakOut();
}
});
}
#Override
public void onDestroy() {
// Don't forget to shutdown tts!
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
btnSpeak.setEnabled(true);
speakOut();
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
private void speakOut() {
String text = txtText.getText().toString();
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
}
I had the same problem. I solved it by implementing the tts service a little bit different:
in onCreate:
TextToSpeech tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int i) {
methodSpeek();
}
}, "com.google.android.tts");
This way your text only starts after it is initialized.
Your code is playing dynamically generated speech as soon as it possibly can, because you are calling
speakOut() in the onInit() method, which is the callback that fires when the text-to-speech synthesizer is ready to use.
If you want to generate speech even sooner, and you know ahead of time the phrase to speak and the locale in which to speak it, you can pregenerate synthetic speech, save it into a WAV file, and play it back later with MediaPlayer:
HashMap<String, String> myHashRender = new HashMap();
String wakeUpText = "Are you up yet?";
String destFileName = "/sdcard/myAppCache/wakeUp.wav";
myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText);
mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);
See the article for details.
When my app is first installed or opened after being destroyed, it works great. If you back out of it and go back in, then the onStart in UtteranceProgressListener never fires after onInit in OnInitListner. When I open the app after backing out, everything else seems to be working. Log shows that onInit is called, but it never progresses to the onStart in the UtteranceProgressListener. How can I make this work?
in my onCreate:
// Implement Text to speech feature
tts = getTts();
// set progress listener to the TTS engine
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
Log.d("LOOK AT ME!!!", "ttsUtteranceListener - onStart");
}
#Override
public void onError(String utteranceId) {
Log.d("LOOK AT ME!!!", "ttsUtteranceListener - onError");
}
#Override
public void onDone(String utteranceId) {
Log.d("LOOK AT ME!!!", "ttsUtteranceListener - onDone");
if (processStarted) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("LOOK AT ME!!!",
"ttsUtteranceListener - speech,startListening");
speech.startListening(intent);
}
});
} else {
...
}
processStarted = false;
}
});
and here is "getTts()":
private TextToSpeech getTts() {
if (tts == null) {
// Implement Text to speech feature
tts = new TextToSpeech(this, new OnInitListener() {
#Override
public void onInit(int status) {
Log.d("LOOK AT ME!!!", "ttsInitListener - onInit");
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.getDefault());
} else {
tts = null;
Toast.makeText(MainActivity.this,
"Failed to initialize TTS engine.",
Toast.LENGTH_SHORT).show();
}
}
});
}
return tts;
}
and here are my lifecycle calls (onPause and onResume) :
// --- LIFECYCLE ---
#Override
public void onResume() {
super.onResume();
Log.d("LOOK AT ME!!!", "onResume");
if (tts == null) {
tts = getTts();
}
}
#Override
public void onPause() {
// Stop then shut down the TextToSpeech Engine
if (tts != null) {
tts.stop();
tts.shutdown();
tts = null;
}
super.onPause();
}
I am using this kind of text to speech in one of my class in my app(Code edited to show outlook & exact requirement.). I will show some content on my view & if we click the button , I want to play the sound that is by using this texttospeech engine... But for First time it is not playing the sound. From the next click onwards the TEXTTOSPEECH engine is working nicely
Iwant to know how to overcome this issue....
public class LearnActivity extends Activity implements OnClickListener, OnInitListener {
AudioManager audioManager;
float volume;
TextToSpeech textToSpeech;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_learn);
textToSpeech = new TextToSpeech(this, this);
textToSpeech.setLanguage(Locale.US);
textToSpeech.setSpeechRate(0.95f);
method();
}
public void method(){
bt.setonClickListener(new onClickListener(){
public void onClick(View v){
playSound(datasource.getItemSound);
}
});
}
public void playSound(String sound){
textToSpeech.speak(sound,TextToSpeech.QUEUE_FLUSH,null);
}
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
}
NOTE:- This also meet my Requirement, How to play sound from TEXTTOSPEECH engine directly without using any onClicks etc.,... because I also wants to play a startup sound that too with Android's Text-To-Speech engine only...
That's because you are clicking the button before the engine is ready.
You have to check if the TTS engine has successfully initialized on your onInit() method and enable/disable the play button accordingly.
Assuming that bt in your code is some sort of View that has setEnabled(boolean) method:
#Override
public void onInit(int status) {
bt.setEnabled(status == TextToSpeech.SUCCESS);
}
You always have to assume that the engine has not been initialized and hence keep your play button disabled by default.
I used RXJava to make a class that solves this problem. If your TTS engine is not ready when you want to use the speak method it will wait for the engine to get ready and then speaks the given string.
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.util.Pair;
import android.widget.Toast;
import java.util.Locale;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
public class Pronunciation {
private TextToSpeech textToSpeech;
private int languageResult;
private boolean noError;
private final String errorMessage="Something went wrong with your text to speech engine";
private PublishSubject<Boolean> engineIsReady=PublishSubject.create();
private PublishSubject<Pair<String,Integer>> speakObservable=PublishSubject.create();
private CompositeDisposable compositeDisposable=new CompositeDisposable();
public Pronunciation(Context context) {
textToSpeech=new TextToSpeech(context, status -> {
if (status!=TextToSpeech.ERROR){
languageResult= textToSpeech.setLanguage(Locale.ENGLISH);
engineIsReady.onNext(true);
} else {
Toast.makeText(context,errorMessage
,Toast.LENGTH_LONG).show();
}
});
if (languageResult==TextToSpeech.LANG_MISSING_DATA||languageResult== TextToSpeech.LANG_NOT_SUPPORTED){
noError =false;
Toast.makeText(context,errorMessage
,Toast.LENGTH_LONG).show();
}else { noError =true;}
compositeDisposable.add( Observable.combineLatest(speakObservable, engineIsReady,
(stringIntegerPair, aBoolean) -> stringIntegerPair)
.subscribeOn(Schedulers.io())
.subscribe(pair->{
if (noError)
textToSpeech.speak( (pair).first
,(pair).second,null,null);
}));
}
public void speak(String text,int queueMode){
speakObservable.onNext(new Pair<>(text,queueMode));
}
public void stop(){
if (textToSpeech!=null){
textToSpeech.stop();
textToSpeech.shutdown();
}
compositeDisposable.clear();
}
}
first add RxJava dependency in your Gradle file
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
Then create an instance of this class in the onCreate method of your activity or fragment.Now you can pass the string and queue mode to the speak method.
pronunciation.speak("Hi", TextToSpeech.QUEUE_FLUSH));
Don't forget to call the stop method in onDestroy or onDetach to avoid memory leak
#Override
public void onDetach() {
super.onDetach();
pronunciation.stop();
}
you should write your program ...
public class MainActivity extends Activity implements TextToSpeech.OnInitListener, OnUtteranceCompletedListener {
TextToSpeech t1;
protected void onCreate(Bundle savedInstanceState) {
t1=new TextToSpeech(MainActivity.this, MainActivity.this);
}/////on creat
protected void onDestroy() {
if(t1!=null) {
t1.stop();
t1.shutdown();
t1=null;
}
super.onDestroy();
}
public void onInit(int arg0) {
t1.setOnUtteranceCompletedListener(this);
}
}//mainactivity
Add this command when button is clicked or everywhere you want to speak text.
t1.speak(text, TextToSpeech.QUEUE_FLUSH, null);
Just Put Delay For 5 Second And It's Working without any button Click
public class Final_Text_To_Speech_Activity extends AppCompatActivity implements TextToSpeech.OnInitListener {
private TextToSpeech tts; // For Text to Speech
CardView ScanProduct, SearchProduct;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TextToSpeech(this, this);
init();
// Just Put Delay For 5 Second And It's Working without any button Click
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
SpeakOutOnce("Welcome to Text To Speech Application");
}
}, 5000);
}
#Override
protected void onResume() {
super.onResume();
}
public void init() {
ScanProduct = (CardView) findViewById(R.id.scan_product);
SearchProduct = (CardView) findViewById(R.id.search_product);
// Search On Button Click
ScanProduct.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
speakOut("You have Just pressed Scan Option");
}
});
SearchProduct.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
speakOut("You have Just pressed Search Option ");
}
});
}
#Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
public void onInit(int status) {
int result = tts.setLanguage(Locale.US);
if (status == TextToSpeech.SUCCESS) {
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
} else {
speakOut("");
}
} else if (status == TextToSpeech.ERROR) {
Toast.makeText(this, "Sorry! Text To Speech failed...",
Toast.LENGTH_LONG).show();
}
}
private void speakOut(String text) {
tts.setPitch(1.0f); //Normal Pitch
tts.setSpeechRate(0.7f); // 1.0 is Normal speech Rate
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
private void SpeakOutOnce(String text) {
if (tts != null) {
tts.setPitch(1.0f); //Normal Pitch
tts.setSpeechRate(0.7f); // 1.0 is Normal speech Rate
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
}
}