TTS initialization error was observed in the following scenarios, that too randomly.
TTS engine is installed, voice set is present and sample tts can be played from the Accessibility options.
The TTS initialization fails randomly on the same device where it was previously initialized and playing.
This issue was observed in different devices(One plus,Asus,Samsung) and various Android OS versions.
Code Snippet:
public class TTSHandler implements OnInitListener {
public EPUBReader context;
private TextToSpeech tts;
private HashMap<String, String> ttsMap;
private boolean isTtsPlaying = false,shouldResume = false,initialised = false,
ttsModeEnabled = false;
private String textToRead;
private GoogleVersionPreferences mSharedPreferences;
private AudioManager mAudioManager;
@SuppressWarnings("deprecation")
public TTSHandler(EPUBReader context){
this.context = context;
tts = new TextToSpeech(context,this);
}
@Override
public void onInit(int status) {
Log.d("TTS", "onInit called");
if(status == TextToSpeech.SUCCESS){
initialised = true;
Log.d("TTS", "initialised success: status = "+status);
initTTSComponents();
}else{
initialised = false;
Log.d("TTS", " initialised failed: status ="+status);
}
}
/**
* called form JavascriptInterface
* @param text is the sentence to be read
*/
public void readText(String text){
if(text!=null){
textToRead = text;
}
ttsMap = new HashMap<String, String>();
ttsMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, textToRead);
//for Next/Prev
isTtsPlaying = true;
context.runOnUiThread(new Runnable(){
@Override
public void run() {
context.toggleTtsIcons();
}
});
tts.speak(textToRead,0, ttsMap);
}
/**
* called to play,pause or resume tts play.
*/
public void playPauseReading(){
context.lockOrientationChange();
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int volume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
if(isTtsPlaying){
isTtsPlaying = false;
shouldResume = true;
tts.stop();
}else{
isTtsPlaying = true;
if(shouldResume){
shouldResume = false;
requestAudioFocusForTTS();
JavaScriptInterface.loadJavascript("javascript:resumeUsingTts()", context.getEPUBReaderFragment().getWebview());
}else{
requestAudioFocusForTTS();
if(volume <= 1){
Toast.makeText(context,context.getResources().getString(R.string.tts_volume_alert), 300).show();
}
int dir = mSharedPreferences.getEpubNavigationSetting(context.bookId);
JavaScriptInterface.loadJavascript("javascript:playFromRange("+dir+")", context.getEPUBReaderFragment().getWebview());
}
}
context.toggleTtsIcons();
}
/**
* called to stop playing tts
* highlight will be removed and we will hide the tts controls
*/
public void stopReading(){
if(tts !=null && ttsModeEnabled){
isTtsPlaying = false;
shouldResume = false;
ttsModeEnabled = false;
tts.stop();
Toast.makeText(context,context.getResources().getString(R.string.tts_stop) , 300).show();
JavaScriptInterface.loadJavascript("javascript:stopUsingTts()",
context.getEPUBReaderFragment().getWebview());
abandonAudioFocus();
context.runOnUiThread(new Runnable(){
@Override
public void run() {
context.toggleControlPanel(false);
context.unlockOrientationChange();
context.invalidateOptionsMenu();
}
});
}
}
/**
* To check the whether tts is playing or not
* @return
*/
public boolean isReading(){
if(tts.isSpeaking()){
return true;
}
return false;
}
/**
* called from javascriptInterface at the end of a chapter
*
*/
public void stopReadingOnEndOfChapter(){
Log.d("TTS", "stopReadingOnEndOfChapter");
shouldResume = false;
isTtsPlaying = false;
ttsModeEnabled = false;
abandonAudioFocus();
context.runOnUiThread(new Runnable(){
@Override
public void run() {
context.toggleControlPanel(false);
context.unlockOrientationChange();
context.invalidateOptionsMenu();
Toast.makeText(context,context.getResources().getString(R.string.end_of_chapter) , 300).show();
}});
}
/**
* called from javascriptInterface to disable tts mode when the chapter doesnt have any text content.
*/
public void stopOnNoContent(){
Toast.makeText(context,context.getResources().getString(R.string.tts_no_content) , 300).show();
shouldResume = false;
isTtsPlaying = false;
ttsModeEnabled = false;
abandonAudioFocus();
context.runOnUiThread(new Runnable(){
@Override
public void run() {
context.toggleControlPanel(false);
context.unlockOrientationChange();
context.invalidateOptionsMenu();
}});
}
/**
* called from javascript to stop tts while user taps on links
*/
public void stopTtsOnLinks(){
if(isReading() || shouldResume)
Toast.makeText(context,context.getResources().getString(R.string.tts_stop) , 300).show();
shouldResume = false;
isTtsPlaying = false;
ttsModeEnabled = false;
tts.stop();
context.toggleControlPanel(false);
context.unlockOrientationChange();
abandonAudioFocus();
}
/**
* Will release the resources used by the TTS engine
*/
public void shutDownTTS(){
if(tts !=null){
tts.shutdown();
}
}
/**
* called from EPUBReader to set the speech rate
* @param speechRate
*/
public void setSpeechRate(int value){
switch(value){
case 0:
tts.setSpeechRate((float)0.1);
break;
case 1:
tts.setSpeechRate((float)0.5);
break;
case 2:
tts.setSpeechRate((float)1);
break;
case 3:
tts.setSpeechRate((float)1.5);
break;
case 4:
tts.setSpeechRate((float)2);
break;
}
}
/**
* called form EPUBReader to start playing the next line
*/
public void playNext(){
isTtsPlaying = false;
tts.stop();
JavaScriptInterface.loadJavascript("javascript:readNext()",context.getEPUBReaderFragment().getWebview());
}
/**
* called form EPUBReader to start playing the previous line
*/
public void playPrevious(){
isTtsPlaying = false;
tts.stop();
JavaScriptInterface.loadJavascript("javascript:playPrevious()",context.getEPUBReaderFragment().getWebview());
}
/**
* if TTS engine is initialised successfully,
* we will set the listener and other components.
*/
private void initTTSComponents(){
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
tts.setSpeechRate(1);
mSharedPreferences = GoogleVersionPreferences.getGoogleAppVersion(context);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
Log.d("TTS", "onStart:"+utteranceId);
}
@Override
public void onError(String utteranceId) {
Log.d("TTS", "onError ID:"+utteranceId);
}
@Override
public void onDone(String utteranceId) {
Log.d("BUG", "onDone, isTtsPlaying:"+isTtsPlaying);
if(isTtsPlaying){
JavaScriptInterface.loadJavascript("javascript:readNext();",
((EPUBReader) context).getEPUBReaderFragment().getWebview());
}
}
});
}
/**
* Requests audio focus so that when TTS starts
* other audio apps will be paused/ducked as per the app.
*/
private void requestAudioFocusForTTS(){
mAudioManager.requestAudioFocus(null,AudioManager.STREAM_MUSIC , AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE);
}
/**
*Will abandon the received audio Focus so that the
*previous app can attain it.
*/
private void abandonAudioFocus(){
mAudioManager.abandonAudioFocus(null);
}
/**
* getters and setters
* @param value
*/
public void setisTtsPlaying(boolean value){
isTtsPlaying = value;
}
public boolean isTtsPlaying(){
return isTtsPlaying;
}
public void setshouldResume(boolean value){
shouldResume = value;
}
public boolean shouldResume(){
return shouldResume;
}
public boolean isTtsInitialised(){
return initialised;
}
public boolean ttsModeEnabled(){
return ttsModeEnabled;
}
public void setttsModeEnabled(boolean value){
ttsModeEnabled = value;
}
}
Note: Logs collected:
For Samsung device(TabS 10.5 OS:5.0.2): E/SamsungTTS(20259): onLoadLanguage() - SamsungTTS is not yet ready.
For One plus one(OS:6.0.1):
08-08 18:54:53.112: W/TextToSpeech(22946): stop failed: TTS engine connection not fully set up 08-08 18:56:15.869: I/TextToSpeech(22946): Sucessfully bound to com.google.android.tts 08-08 18:56:16.060: I/TextToSpeech(22946): Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
I had this TTS Initialization failed because I was using Android 11 Emulator and it requires to mention this in the Android Manifest
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With