2

I have an application using TTS very heavily. It's working fine, but I need to tweak it.

I am using a TTS object in every screen and this is not good. I wish I could creat the TTS object just once (like a Singleton) and them, use it throughout all my activities.

Here is the base code for this to work:

    public class SimOuNaoActivity extends Activity implements OnInitListener{
    public TextToSpeech tts;
        private int MY_DATA_CHECK_CODE = 0;


        @Override
        public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);
    Intent checkIntent = new Intent();
    checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
    startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
    tts.speak("Testing 1,2,3", TextToSpeech.QUEUE_ADD, null);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            tts = new TextToSpeech(this, this);
        } else {
            // missing data, install it
            Intent installIntent = new Intent();
            installIntent
                    .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            startActivity(installIntent);
        }
    }

}

@Override
public void onInit(int status) {
    if (status == TextToSpeech.SUCCESS) {
        // Toast.LENGTH_LONG).show();
    } else if (status == TextToSpeech.ERROR) {
        // Toast.LENGTH_LONG).show();
    }
}

@Override
public void onDestroy() {
    if (tts != null) {
        tts.stop();
        tts.shutdown();
    }
    super.onDestroy();
       System.gc();
    }

    }

What is the correct approach to have the TTS object available in all my activities? Have in mind that it uses some methods like startActivityForResult, etc... so... I would like to know what I can do to make this work fine.

Can anyone help me, please?

Any help is appreciatted!

Thanks!

Carlos Pereira
  • 1,914
  • 6
  • 24
  • 35
  • 1
    Well, what is preventing you from setting up the TextToSpeech object as a Singleton? Sounds like a sensible thing to do in your use case. You could potentially set it up in your own Application subclass to easily access it from all activities, or, perhaps more convenient, create some sort of base activity with relevant methods that delegates calls to the TextToSpeech object from the Singleton/Application and have all other activities extend this. – MH. Feb 24 '12 at 23:20
  • Hello MH, thank you for your answer. Any sample code? I am kinda of stuck in here =P – Carlos Pereira Feb 25 '12 at 00:13
  • In stead of copy-pasting code in here, I suggest you have a look at [this almost identical topic](http://stackoverflow.com/questions/8159749/global-tts-in-android). Another implementation of TTS using a Singleton pattern can be found [here](http://www.androidadb.com/source/and-bible-read-only/AndBible/src/net/bible/android/device/TextToSpeechController.java.html). Do note there's not really a consensus on using [Singleton vs. Application](http://stackoverflow.com/questions/3826905/singletons-vs-application-context-in-android). I'll leave that decision up to you. Good luck. :) – MH. Feb 25 '12 at 00:30

3 Answers3

1

This is relatively simple - Just implement it as follows and do not forget to pass as context, the application context (this.getApplicationContext()) and not the activity context.

public class SingletonTTS {

private static SingletonTTS instance;
private static Context ctx;
private TextToSpeech mTTS;
private static boolean TTSready = false;

private SingletonTTS(Context context) {
    ctx = context;
    mTTS = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int i) {
            TTSready = true;
            configTTS();

        }
    });
}

public static synchronized SingletonTTS getInstance(Context context) {
    if (instance == null) {
        instance = new SingletonTTS(context);
    }
    return instance;
}

public static boolean isTTSready(){
    return TTSready;
}

private void configTTS() {
    Toast.makeText(ctx, "supports " + mTTS.isLanguageAvailable(Locale.getDefault()), Toast.LENGTH_LONG).show();
    int available = mTTS.isLanguageAvailable(Locale.getDefault());
    if( available != TextToSpeech.LANG_MISSING_DATA
            && available != TextToSpeech.LANG_NOT_SUPPORTED ){
        mTTS.setLanguage(new Locale(Locale.getDefault().getLanguage()) );

    } else {
        /** TODO SAVE */
    }

}

public void speakSentence(String sentence){
    mTTS.speak(sentence, TextToSpeech.QUEUE_ADD, null);
}

}

J. Murray
  • 1,460
  • 11
  • 19
  • Application context and Activity context is the same exact thing. That's because `Activity` extends `ContextWrapper`, which is the class that implements `getApplicationContext` – kenny_k Oct 25 '19 at 06:11
  • They are both instances of Context, but the application instance is tied to the lifecycle of the application, while the Activity instance is tied to the lifecycle of an Activity. Thus, they have access to different information about the application environment. – Javier Castellanos Cruz Oct 28 '19 at 17:20
  • Yes, sure- I think you should edit the last part of your answer to be more clear what you mean - "and not the activity _context_" -> "and not the activity _instance_" – kenny_k Oct 28 '19 at 20:42
0

Have a look here to share stuff between activities and program with nicer design in android : Intent.putExtras size limit?

Community
  • 1
  • 1
Snicolas
  • 37,840
  • 15
  • 114
  • 173
0

You'll likely want to instantiate and hold your Singleton object in the Application, which can only be instantiated once anyway, so just put your TTS initialisation code in a class of its own and instantiate that class as an object in your Application. You'll need to pass the Application to your TTS class as the Context that TTS will be instantiated with.

public class MyApplication extends Application {
    public MyTTS myTTS;
    public void onCreate() {
        myTTS = new MyTTS(this);
    }
}

then you can use getApplication().myTTS.whateverMethodsYouMake(yadayada) from within Activities to access the Application-Singleton-ified TTS class.

straya
  • 5,002
  • 1
  • 28
  • 35