0

アプリでテキスト読み上げを使用していますが、すべてのボタンで正常に機能するようになりました。ただし、スプラッシュ アクティビティでテキスト読み上げを使用しようとすると、アプリがクラッシュします。これは nullpointer 例外であるため、コーディングが間違っていることはわかっています。やりたいことを明確にする。スプラッシュ活動中にしゃべってほしい。スプラッシュ アクティビティがスリープ状態になったら、もう一度話し、読み込みが完了したことをユーザーに伝えたいと思います。スプラッシュ アクティビティ用の Java を含めました。

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();
        }
    }

}
4

3 に答える 3

1

寝た直後のスレッドの冒頭で、speakWords を呼び出しています。myTTS.speak を呼び出します。その時点でコードを見ると、myTTS は初期化されていないようで、null であるため、NPE でクラッシュします。

このコードは NPE を防ぐはずですが、TTS エンジンの初期化に時間がかかりすぎると、Loading と表示されません。また、5 秒 (これは非常に長い時間です) のスリープは、初期化できるようにするためのものだと思いますか?

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();
    }
}

}

于 2012-07-27T13:08:29.397 に答える
1

あなたのアプローチには2つの問題があります。

まず、アプリはinit()話し始める前に待機する必要があります。次に、アプリは、音声ライブラリが利用できない場合に処理する必要があります。

このクラスまたはこのクラスを使用して、TextToSpeech の初期化を支援します。それは実際には複雑であり、使用することTextToSpeech.Engine.ACTION_CHECK_TTS_DATAは実際には最善の方法ではありません。

于 2012-07-27T15:27:50.523 に答える
1

TTS エンジンがロードされた後でスニペットを少し読み込んでいると呼び出したほうがよいので、OnActivityResult() に発言を入れることができます。

あなたのコードでは、speak を呼び出すときに myTTS が初期化されているかどうかを実際に判断することはできません。このようにしてみてください:

                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);

      try {
                    sleep(5000);
                    speakWords("loading");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
于 2012-07-27T13:12:13.533 に答える