I've looked at several threads asking about running TTS from a service, (sorry, can't remember which ones) but none of them help.
The IntentService starts just fine, but it's destroyed before onInit() is run which is what I believe is causing this logcat:
07-28 18:58:24.716 2305-2305/me.arthurtucker.alfredjr D/MainActivity: onPrefChange
07-28 18:58:24.786 2305-2305/me.arthurtucker.alfredjr D/MainActivity: made new intent
07-28 18:58:24.794 2305-2305/me.arthurtucker.alfredjr D/MainActivity: started service
07-28 18:58:25.044 2305-2305/me.arthurtucker.alfredjr I/SpeachService: onCreate() ran
07-28 18:58:25.255 2305-2573/me.arthurtucker.alfredjr I/TextToSpeech: Sucessfully bound to com.google.android.tts
07-28 18:58:25.255 2305-2573/me.arthurtucker.alfredjr I/SpeachService: onHandleIntent ran
07-28 18:58:25.255 2305-2305/me.arthurtucker.alfredjr W/TextToSpeech: stop failed: not bound to TTS engine
07-28 18:58:25.255 2305-2305/me.arthurtucker.alfredjr W/TextToSpeech: shutdown failed: not bound to TTS engine
07-28 18:58:25.255 2305-2305/me.arthurtucker.alfredjr I/SpeachService: onDestroy() ran
07-28 18:58:25.286 2305-2305/me.arthurtucker.alfredjr E/ActivityThread: Service me.arthurtucker.alfredjr.SpeechService has leaked ServiceConnection android.speech.tts.TextToSpeech$Connection@37ad3e10 that was originally bound here
android.app.ServiceConnectionLeaked: Service me.arthurtucker.alfredjr.SpeechService has leaked ServiceConnection android.speech.tts.TextToSpeech$Connection@37ad3e10 that was originally bound here
at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
at android.app.ContextImpl.bindService(ContextImpl.java:1437)
at android.app.ContextImpl.bindService(ContextImpl.java:1426)
at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
at android.speech.tts.TextToSpeech.connectToEngine(TextToSpeech.java:627)
at android.speech.tts.TextToSpeech.initTts(TextToSpeech.java:597)
at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:553)
at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:527)
at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:512)
at me.arthurtucker.alfredjr.SpeechService.onHandleIntent(SpeechService.java:37)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:60)
I've tried running sayString() in onCreate(), onHandleIntent(), and now onInit(). When in onCreate() or onHandleIntent() the logcat reports something like: "speak failed: not bound to tts engine”.
Is there a way to have the IntentService wait for onInit() to run before destroying?
My code is below.
public class SpeechService extends IntentService implements TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener {
private static TextToSpeech myTTS;
private Main mActivity;
private static final String TAG = "SpeachService";
//private String msg;
public SpeechService() {
super("SpeechService");
}
@Override
public void onCreate() {
mActivity = new Main();
super.onCreate();
Log.i(TAG, "onCreate() ran");
}
@Override
protected void onHandleIntent(Intent intent) {
Intent checkTTSIntent = new Intent();
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
myTTS = new TextToSpeech(this, this);
//String msg = intent.getStringExtra("imsg");
Log.i(TAG, "onHandleIntent ran");
}
public void sayString(String string) {
if (myTTS != null) {
if (mActivity.mEnabled) {
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS, "true");
myTTS.speak(string, 1, hashMap);
} else {
myTTS.speak(string, 1, null);
}
}
Log.i(TAG, "sayString() ran");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
if (myTTS != null) {
myTTS.stop();
myTTS.shutdown();
}
super.onDestroy();
Log.i(TAG, "onDestroy() ran");
}
@Override
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
if (myTTS.isLanguageAvailable(Locale.UK) == TextToSpeech.LANG_AVAILABLE) {
myTTS.setLanguage(Locale.UK);
}
sayString("IT WORKS");
} else if (initStatus == TextToSpeech.ERROR) {
mActivity.makeToast("Failed to start Text-to-Speech Service", true);
}
Log.i(TAG, "onInit() ran");
}
@Override
public void onUtteranceCompleted(String s) {
stopSelf();
Log.i(TAG, "onUtteranceCompleted() ran");
}
}
I'd be willing to try something completely different method, as long as it does something similar.
You are not calling onInit()
explicitly. IntentService
is destroyed once the onHandleIntent
method is invoked. Make sure you do all your work in onHandleIntent
method.
onHandleIntent(Intent intent) from the Documentation:
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().