最近在写一个安卓语音识别的项目,结果助教要求将其中的dialog变成voice dialog,也就是首先要把dialog的内容读出来,然后让用户说"yes"或者"no"触发相应的操作。本来不是很难,只需要在tts的callback中的onDone方法触发新的语音识别即可,但是遇到了一点小问题让我debug了两天。
首先上代码,这是tts的类
public class SpeechForDialog {
TextToSpeech tts;
protected Context context;
protected String words="";
public SpeechForDialog(Context c,String s){
this.context=c;
this.words=s;
initSpeech();
}
private void initSpeech(){
tts=new TextToSpeech(context.getApplicationContext(), new ttsInitListener());
}
private class ttsInitListener implements TextToSpeech.OnInitListener {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
if (tts!=null&&!tts.isSpeaking()) {
CharSequence cs=words;
tts.setLanguage(Locale.US);
tts.setOnUtteranceProgressListener(new ttsUtteranceListener());
tts.speak(cs, TextToSpeech.QUEUE_FLUSH, null, null);
}
}
else if(status == TextToSpeech.ERROR){
tts = null;
Toast.makeText(context,"Error",Toast.LENGTH_SHORT).show();
}
}
}
private class ttsUtteranceListener extends UtteranceProgressListener{
@Override
public void onStart(String utteranceId) {
}
@Override
public void onDone(String utteranceId) {
Toast.makeText(a, "toast", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(String utteranceId) {
}
}
}
然后在MainActivity里使用 :
new SpeechForDialog(this,"this is the text to speech test");
结果发现,尽管"this is the text to speech test"确实能读出来,但是onDone方法里的Toast并没有弹出。
原因是,speak方法有四个参数
public int speak (CharSequence text, int queueMode, Bundle params, String utteranceId)
再看UtteranceProgressListener的说明:
Listener for events relating to the progress of an utterance through the synthesis queue. Each utterance is associated with a call to speak(CharSequence, int, Bundle, String) or synthesizeToFile(CharSequence, Bundle, File, String) with an associated utterance identifier, as per KEY_PARAM_UTTERANCE_ID. The callbacks specified in this method can be called from multiple threads.
这表示UtteranceProgressListener需要一个id,但我在使用speak的时候第四个参数设置成了null,导致UtteranceProgressListener没法触发,所以把代码
tts.speak(cs, TextToSpeech.QUEUE_FLUSH, null, null);
修改为
tts.speak(cs, TextToSpeech.QUEUE_FLUSH, null, "UniqueID");
@Override
public void onDone(String utteranceId) {
final Activity a=(Activity)context;
a.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(a, "kkkk", Toast.LENGTH_SHORT).show();
}
});
}
关于toast和thread的关系就不在这里细说了,总之修改完成后,toast就可以触发了!