title: How to run an Android TTS in an IntentService
body: <p>I've looked at several threads asking about running TTS from a service, (sorry, can't remember which ones) but none of them help. </p>
  
  <p>The IntentService starts just fine, but it's destroyed before onInit() is run which is what I believe is causing this logcat:</p>
  
  <pre><code>    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.&lt;init&gt;(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.&lt;init&gt;(TextToSpeech.java:553)
          at android.speech.tts.TextToSpeech.&lt;init&gt;(TextToSpeech.java:527)
          at android.speech.tts.TextToSpeech.&lt;init&gt;(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)
  </code></pre>
  
  <p>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”.</p>
  
  <p>Is there a way to have the IntentService wait for onInit() to run before destroying?</p>
  
  <p>My code is below.</p>
  
  <pre><code>    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&lt;String, String&gt; hashMap = new HashMap&lt;String, String&gt;();
                  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");
      }
  }
  </code></pre>
  
  <p>I'd be willing to try something completely different method, as long as it does something similar.</p>