我遇到了isSpeaking()
方法的问题。将QUEUE_FLUSH
传递给speak()
方法时,isSpeaking()
工作正常。但是,当我对多个话语进行排队时(通过传递QUEUE_ADD
),isSpeaking()
方法会在多个话语排队后立即开始返回false
。
然后我偶然发现了the source code of the TtsService
class并看到了这段代码:
public boolean isSpeaking() {
return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1));
}
有没有人有任何想法,为什么这种方法以这种方式实施?
答案 0 :(得分:8)
我偶然发现了这个。
自从你提出这个问题已经过去了一年,没有答案可以解决......
所以我只能猜到编写这段代码的人意图表示
“只有在说出最后话语时才会这样做。
这有意义吗?
唯一的问题是,无论是QUEUE_ADD
还是QUEUE_FLUSH
模式,经验观察都表明存在严重的时间竞争条件:
isSpeaking()
中调用,onUtteranceCompleted()
将始终返回 false 。isSpeaking()
将始终返回 true ,如果在tts.speak()
之后第一次 onUtteranceCompleted()
之后立即调用。isSpeaking()
将始终返回 false ,如果在tts.speak()
之后立即调用,tts.speak()
之间至少再有onUtteranceCompleted()
个{{1}}在最后{{1}}之间分隔和它本身。在某种程度上,它的行为完全与“预期”相反:
“仅在说出第一个话语”时(在 onUtteranceCompleted()之后)
为什么它表现得像这样超出了我,但这至少是LogCat所展示的。
另请注意official documentation的以下内容:
“请注意,一旦语音项目的音频数据被认为是完整的 已被发送到音频混音器,或写入文件。可能有 此点之间以及音频硬件完成时的有限延迟 回放。“
换句话说,这种方法完全没用。
答案 1 :(得分:4)
队列完成时有广播意图:ACTION_TTS_QUEUE_PROCESSING_COMPLETED。
这是一个注册BroadCastReceiver并使用它来确定isSpeaking状态的示例类。
从您活动的相关位置呼叫初始化和关闭,并使用此课程中提供的Speak和isSpeaking功能:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
public class SpeechWrapper {
private static TextToSpeech mTts = null;
private static boolean isSpeaking = false;
private static BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED) && mTts != null)
{
isSpeaking = false;
}
}
};
private static void Speak(String sMessage, int intQueueType, int delay) {
if (mTts == null || sMessage == null) return;
sMessage = sMessage.trim();
isSpeaking = true;
if (delay > 0) {
mTts.playSilence(delay, intQueueType, null);
intQueueType = TextToSpeech.QUEUE_ADD;
}
mTts.speak(sMessage, intQueueType, null);
}
public static void Init(Context context) {
mTts = new TextToSpeech(context, (OnInitListener) context);
IntentFilter filter = new IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
context.registerReceiver(receiver, filter);
}
public static void Shutdown() {
if (mTts != null) {
mTts.stop();
mTts.shutdown();
}
}
public static boolean isSpeaking() {
return isSpeaking;
}
}