Android使用ExoPlayer播放视频时TextToSpeech不朗读首个视频名称问题求助
问题根因
TextToSpeech的初始化是异步操作,你在onCreate中初始化TTS之后立刻调用朗读第一个视频名称的逻辑时,onInit回调还没执行完成,TTS实例还没处于就绪状态,所以第一次朗读请求直接被丢弃了。后续视频朗读时TTS已经初始化完成,所以可以正常执行。
解决方案
1. 新增全局变量存储状态和待朗读内容
var tts: TextToSpeech? = null // 新增两个变量 private var isTtsReady = false private var pendingSpeakContent: String? = null
2. 修改onInit回调
初始化成功后标记就绪状态,同时检查是否有待朗读的内容,有就直接执行朗读:
override fun onInit(status: Int) { val myLanguage = Locale.getDefault().displayLanguage if (androidAPILevel < 21) { val params: HashMap<String, String> = HashMap() params[TextToSpeech.Engine.KEY_PARAM_VOLUME] = musicVolume.toString() } else { val params = Bundle() params.putFloat( TextToSpeech.Engine.KEY_PARAM_VOLUME, musicVolume.toFloat() ) } if (status == TextToSpeech.SUCCESS) { val result = tts!!.setLanguage(Locale.FRENCH) if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { Log.e("TTS", "*************** 该语言不受支持 ***************") speakOut("French not supported, install it please") showTheToast(getString(R.string.NoJapaneseLanguage)) } else { tts!!.setSpeechRate(1.0f) // 新增逻辑:标记TTS就绪,读取待朗读内容 isTtsReady = true pendingSpeakContent?.let { content -> speakOut(content) pendingSpeakContent = null } } } else { showTheToast("TextToSpeech初始化失败!") } }
3. 改造speakOut方法适配未就绪场景
private fun speakOut(content: String) { tts ?: return // TTS未就绪时先缓存内容,等初始化完成后再读 if (!isTtsReady) { pendingSpeakContent = content return } // 原有朗读逻辑,注意适配不同API版本 if (androidAPILevel < 21) { val params: HashMap<String, String> = HashMap() params[TextToSpeech.Engine.KEY_PARAM_VOLUME] = musicVolume.toString() tts!!.speak(content, TextToSpeech.QUEUE_ADD, params) } else { val params = Bundle() params.putFloat( TextToSpeech.Engine.KEY_PARAM_VOLUME, musicVolume.toFloat() ) tts!!.speak(content, TextToSpeech.QUEUE_ADD, params, null) } }
4. 补充资源释放逻辑
避免Activity销毁时出现内存泄漏:
override fun onDestroy() { tts?.stop() tts?.shutdown() super.onDestroy() }
改造完成后直接调用speakOut方法传入视频名称即可,不需要额外判断TTS状态。
内容的提问来源于stack exchange,提问作者LastCard1440
相关产品推荐
相关产品推荐

