盆栽エンジニアリング日記

勉強したことをまとめるブログ

TextToSpeechが突然喋らなくなった

TextToSpeechが突然喋らなくなった

今TextToSpeechを利用したAndroidアプリを開発しているのですが、ある時から急にTextToSpeechが機能しなくなりました
その原因が分かったのでここにまとめます。
TextToSpeechを利用するに当たって、Android Developersや他サイトのチュートリアルを参考にしました。
ほとんどのチュートリアルはボタンを押したら喋るようになっていましたが、今回開発するアプリは遷移してデータの準備が完了したらユーザーの操作なしに読み上げを開始してほしかったので、onClick内の処理をactivityのメンバ関数として実装して利用していました。結論から言うとこれが落とし穴でした。

TextToSpeechの初期化には時間がかかる

これまで勘違いしていたのですが、TextToSpeechの初期化は実行後にすぐ完了する訳ではなく、ある程度時間がかかるようです。
このため、下記のような実装をすると、初期化が完了する前にspeak関数が実行される可能性があります。
もちろんこの場合、TextToSpeechの初期化が完了していないため、speak関数は失敗します。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news);

        //announcerの初期化
        announcer = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int i) {
                if(i != TextToSpeech.ERROR)
                {
                    announcer.setLanguage(Locale.JAPAN);
                }
            }
        });
    }

//この関数はasynctaskが終了した時に呼ばれる。
private void readArticle()
    {
         announcer.speak(m_htmlList.get(index).getMainContents(), TextToSpeech.QUEUE_FLUSH, null, null);
    }

この様に実装すると、asynctaskの終了がTextToSpeechの初期化よりも早く終わる可能性があるため、不安定です。
つまり、本質的にはチュートリアルのようにボタンのクリックで読み上げを開始するような処理も危険です。
これを防ぐためには、OnInitListenerのonInitで言語を設定した後で読み上げを行うようにする必要があります。