如何查询TextToSpeech队列已处理的语音合成条目数量
解决TextToSpeech中途停止后定位已处理条目的问题
嘿Mike,我完全懂你的困扰——当你用循环把ArrayList里的内容批量加入TTS队列后,中途点击停止却没法准确知道它已经读完了第几条,没法对应到原列表的位置,对吧?
其实Android的TextToSpeech本身并没有直接提供查询队列已完成条目数的API,但我们可以通过UtteranceProgressListener来自己跟踪每个朗读任务的完成状态,这样就能精准记录已处理的条目数量了。
具体实现步骤:
给TextToSpeech设置进度监听器
这个监听器可以监听每个朗读任务的开始、完成和错误状态,我们在里面维护一个计数器,每完成一条就递增计数。// 初始化TextToSpeech时设置监听器 textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() { private int completedUtterances = 0; @Override public void onStart(String utteranceId) { // 可选:任务开始时的逻辑,比如高亮当前朗读条目 } @Override public void onDone(String utteranceId) { // 每完成一条,计数器+1 completedUtterances++; } @Override public void onError(String utteranceId) { // 即使出错,也标记为已处理,避免计数错位 completedUtterances++; } // 提供获取已完成计数的方法 public int getCompletedCount() { return completedUtterances; } // 重置计数器,每次开始新的朗读任务前调用 public void resetCount() { completedUtterances = 0; } });给每个朗读任务添加唯一标识
在调用speak()方法时,需要给每个任务设置一个utteranceId,这样监听器能准确识别每个任务的完成状态(虽然这里我们主要用计数器,但标识是监听器工作的必要条件)。修改你的
speech方法:private void speech(String text) { HashMap<String, String> utteranceParams = new HashMap<>(); // 用当前章节数作为唯一标识,和你的CurChapter对应 utteranceParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(sh.CurChapter)); textToSpeech.speak(text, TextToSpeech.QUEUE_ADD, utteranceParams); }开始朗读前重置计数器
在你的循环开始前,先把计数器清零,避免上次朗读的计数影响:if(!sh.Contents.isEmpty()) { // 重置计数器 ((UtteranceProgressListener)textToSpeech.getOnUtteranceProgressListener()).resetCount(); sh.CurChapter = 0; // 记得把CurChapter重置为0,避免累加之前的数值 for (String object: sh.Contents) { sh.CurChapter += 1; speech(String.valueOf(sh.CurChapter) + " " + object); } } else { speech( "Section not found!"); }点击STOP按钮时获取已处理条目数
当你点击停止按钮时,先调用textToSpeech.stop()终止当前朗读,然后通过监听器的getCompletedCount()拿到已完成的条目数,就能对应到ArrayList的位置了(注意:因为你的CurChapter从1开始计数,所以列表索引是completedCount - 1)。stopButton.setOnClickListener(v -> { textToSpeech.stop(); UtteranceProgressListener listener = (UtteranceProgressListener) textToSpeech.getOnUtteranceProgressListener(); int processedCount = listener.getCompletedCount(); // 检查计数是否在列表范围内 if (processedCount > 0 && processedCount <= sh.Contents.size()) { // 获取对应的列表条目 String targetItem = sh.Contents.get(processedCount - 1); // 在这里对这个条目进行你需要的操作 Log.d("TTS", "已处理到第" + processedCount + "条,内容:" + targetItem); } });
注意事项:
- 确保
UtteranceProgressListener的实现是同一个实例,这样计数器才会保持正确状态。 - 如果你的TTS引擎不支持
KEY_PARAM_UTTERANCE_ID(Android API 21+推荐用Bundle),可以替换成以下写法:Bundle params = new Bundle(); params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(sh.CurChapter)); textToSpeech.speak(text, TextToSpeech.QUEUE_ADD, params, null);
这样就能完美解决你中途停止后定位已处理条目的问题啦!
内容的提问来源于stack exchange,提问作者Mike Dole
相关产品推荐
相关产品推荐

