Search code examples
javaandroidtext-to-speech

Getting text to speech to play on start of an activity without button


I am using text to speech in my app and I have been able to get it to work on all of my buttons fine. However, when I try to use the text to speech in my splash activity it crashes the app. It is a nullpointer exception so I know I am just coding it incorrectly. To clarify what I want it to do. I want it to talk during the splash activity. When the splash activity sleeps I want it to talk again to tell the user it is done loading.I have included the java for my splash activity.

public class mainj extends Activity implements OnInitListener {

    private TextToSpeech myTTS;
    // status check code
    private int MY_DATA_CHECK_CODE = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loadscreen);
        Thread logoTimer = new Thread() {
            public void run() {
                try {
                    try {
                        sleep(5000);
                        speakWords("loading");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    Intent menuIntent = new Intent("android.intent.action.MENU");
                    startActivity(menuIntent);

                    Intent checkTTSIntent = new Intent();
                    checkTTSIntent
                            .setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
                    startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
                }

                finally {
                    finish();
                }
            }

        };
        logoTimer.start();
    }

    // speak the user text
    private void speakWords(String speech) {

        // speak straight away
        myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
    }

    // act on result of TTS data check
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == MY_DATA_CHECK_CODE) {
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                // the user has the necessary data - create the TTS
                myTTS = new TextToSpeech(this, this);
            } else {
                // no data - install it now
                Intent installTTSIntent = new Intent();
                installTTSIntent
                        .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTTSIntent);
            }
        }
    }

    // setup TTS
    public void onInit(int initStatus) {

        // check for successful instantiation
        if (initStatus == TextToSpeech.SUCCESS) {
            if (myTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE)
                myTTS.setLanguage(Locale.US);
        } else if (initStatus == TextToSpeech.ERROR) {
            Toast.makeText(this, "Sorry! Text To Speech failed...",
                    Toast.LENGTH_LONG).show();
        }
    }

}

Solution

  • Right at the beginning of your thread after you sleep you are calling speakWords. that calls myTTS.speak. At that point looking at your code, the myTTS does not seem to be initialized and is null so will crash with an NPE.

    This code should prevent the NPE, but if the initialization of the TTS engine takes too long, then you won't get it to say Loading. Also, I am guessing the 5 second (which is a really long time btw) sleep is to allow for it to get initialized?

    public class mainj extends Activity implements OnInitListener {
    
    private TextToSpeech myTTS;
    // status check code
    private int MY_DATA_CHECK_CODE = 0;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loadscreen);
        Intent checkTTSIntent = new Intent();
        checkTTSIntent
             .setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
        Thread logoTimer = new Thread() {
            public void run() {
                try {
                    try {
                        sleep(5000);
                        speakWords("loading");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
    
                    Intent menuIntent = new Intent("android.intent.action.MENU");
                    startActivity(menuIntent);
    
                }
    
                finally {
                    finish();
                }
            }
    
        };
        logoTimer.start();
    }
    
    // speak the user text
    private void speakWords(String speech) {
    
        // speak straight away
       if(myTTS != null)
       {
            myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
       }
    }
    
    // act on result of TTS data check
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
        if (requestCode == MY_DATA_CHECK_CODE) {
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                // the user has the necessary data - create the TTS
                myTTS = new TextToSpeech(this, this);
            } else {
                // no data - install it now
                Intent installTTSIntent = new Intent();
                installTTSIntent
                        .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTTSIntent);
            }
        }
    }
    
    // setup TTS
    public void onInit(int initStatus) {
    
        // check for successful instantiation
        if (initStatus == TextToSpeech.SUCCESS) {
            if (myTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE)
                myTTS.setLanguage(Locale.US);
        } else if (initStatus == TextToSpeech.ERROR) {
            Toast.makeText(this, "Sorry! Text To Speech failed...",
                    Toast.LENGTH_LONG).show();
        }
    }
    

    }