Android使用TextToSpeech出现空对象引用及onInit不触发问题
问题原因及解决方案
第一阶段自定义TTS工具类崩溃原因
- 你自定义的
cl_txt2speech是普通Java类,不是Android Activity子类,onCreate是Activity专属的生命周期方法,系统不会自动调用这个方法,所以txt2speech对象一直没有被初始化,始终为null,调用setLanguage自然会报空指针。 - 就算你手动调用
onCreate方法,类里的context成员变量也没有赋值,调用context.getApplicationContext()同样会触发空指针。 - TextToSpeech初始化是异步操作,就算初始化代码正确执行,也不能立刻调用
setLanguage、speak等方法,必须等onInit回调触发且返回成功状态后再操作。
第二阶段迁移到Activity后onInit不触发的原因及解决方案
原因
最常见的原因是设备上没有安装可用的TextToSpeech引擎:Android系统本身不自带TTS引擎,需要第三方应用提供实现,比如谷歌文字转语音、讯飞语音+、百度TTS等,国内大部分出厂ROM默认不会预装这类引擎,导致TTS绑定失败,onInit不会回调。
其次是你在onCreate里刚初始化完TextToSpeech就立刻调用getDefaultLanguage、speak等方法,此时还没完成和TTS引擎的绑定,就会报not bound to TTS engine错误。
解决步骤
- 先检查设备是否安装了TTS引擎:可以到系统设置→语言和输入法→文字转语音(TTS)输出,查看是否有可用的引擎,没有的话先安装一款。
- 调整调用逻辑,所有TTS相关操作必须等
onInit回调触发且status为成功后再执行:
@Override public void onInit(int status) { System.out.println( "--------------- onInit() -------------" ); if (status == TextToSpeech.SUCCESS) { txt2speech_available = true; // 初始化成功后再执行语言设置、播报等操作 int result = txt2speech.setLanguage(Locale.FRANCE); if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { // 对应语言不支持,做降级处理 } else { txt2speech.speak("test, 1 2 3", TextToSpeech.QUEUE_FLUSH, null); } } else { // TTS初始化失败,提示用户 Log.e("TTS", "初始化失败,错误码:" + status); } }
- 页面销毁时记得释放TTS资源,避免内存泄漏:
@Override protected void onDestroy() { if (txt2speech != null) { txt2speech.stop(); txt2speech.shutdown(); } super.onDestroy(); }
- 如果要封装TTS工具类,不要用Activity生命周期的写法,改成主动初始化的方式,构造方法传入context,提供初始化回调接口:
public class cl_txt2speech { private TextToSpeech txt2speech; private Context context; private String currentLanguage = ""; private boolean isAvailable = false; private OnInitCallback callback; public interface OnInitCallback { void onSuccess(); void onFail(int errorCode); } public cl_txt2speech(Context context, OnInitCallback callback) { this.context = context.getApplicationContext(); this.callback = callback; // 构造方法里直接初始化 txt2speech = new TextToSpeech(this.context, status -> { if (status == TextToSpeech.SUCCESS) { isAvailable = true; callback.onSuccess(); } else { callback.onFail(status); } }); } // 剩下的语言切换、播报方法里都要先判断isAvailable是否为true,避免空指针 }
工具类调用方式:
cl_txt2speech txt2speech = new cl_txt2speech(FullscreenActivity.this, new cl_txt2speech.OnInitCallback() { @Override public void onSuccess() { // 初始化成功后再调用播报方法 txt2speech.txt2speech_speak("fr", "test, 1 2 3"); } @Override public void onFail(int errorCode) { Toast.makeText(FullscreenActivity.this, "TTS初始化失败", Toast.LENGTH_SHORT).show(); } });
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

