package com.hanghui.senic.common; import android.content.Context; import android.speech.tts.TextToSpeech; import android.text.TextUtils; import com.blankj.utilcode.util.LogUtils; import com.google.gson.Gson; import com.hanghui.senic.MyAppliction; import com.hanghui.senic.service.usbserialdemo.utile.MTTSDemo; import com.hanghui.senic.service.usbserialdemo.utile.StringIsNull; import com.hanghui.senic.service.usbserialdemo.utile.loacat.AppLogUtils; import java.lang.reflect.Field; import java.util.Locale; /** * 语音播报 */ public class MTTSManager implements TextToSpeech.OnInitListener { private static MTTSManager instance; private TextToSpeech mTTS; private String speakContent = ""; public MTTSManager() { if (mTTS == null) { //监听器就直接传入本类 mTTS = new TextToSpeech(MyAppliction.getContext(), this); } } public static synchronized MTTSManager getInstance() { if (instance == null) { instance = new MTTSManager(); } return instance; } public void speak(String text) { if (StringIsNull.IsStringNull(text)) { AppLogUtils.e(true, "TTS语音播报", "语音内容为空 "); return; } AppLogUtils.e(false, "TTS语音播报", "TTS语音播报内容 : " + text); if (ismServiceConnectionUsable(mTTS)) { if (mTTS == null) { mTTS = new TextToSpeech(MyAppliction.getContext(), this); } speakContent = text; //设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规 mTTS.setPitch(1.0f); //设置语速 mTTS.setSpeechRate(1.0f); //TextToSpeech.QUEUE_ADD添加到队列后面,依次将前面的读完轮序 //TextToSpeech.QUEUE_FLUSH刷新队列,将之前的队列取消阅读现在的文字 mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null); } else {//被回收了不可用状态 if (mTTS != null){ mTTS.stop(); mTTS.shutdown(); } mTTS = new TextToSpeech(MyAppliction.getContext(), status -> { if (status == TextToSpeech.SUCCESS) { int result = mTTS.setLanguage(Locale.CHINA); if (result != TextToSpeech.LANG_COUNTRY_AVAILABLE && result != TextToSpeech.LANG_AVAILABLE) { AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言"); } //设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规 mTTS.setPitch(1.0f); //设置语速 mTTS.setSpeechRate(1.0f); mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null); } else { AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: TTS初始化失败"); } }, "com.iflytek.speechcloud");//科大讯飞语音引擎 } } public void init() { //监听器就直接传入本类 mTTS = new TextToSpeech(MyAppliction.getContext(), this); } public void destroy() { if (mTTS != null) { mTTS.stop(); mTTS.shutdown(); mTTS = null; } instance = null; } @Override public void onInit(int status) { if (mTTS == null) { mTTS = new TextToSpeech(MyAppliction.getContext(), this); } //判断是否转化成功 if (status == TextToSpeech.SUCCESS) { //设置语言为中文 int languageCode = mTTS.setLanguage(Locale.CHINESE); //判断是否支持这种语言,Android原生不支持中文,使用科大讯飞的tts引擎就可以了 if (languageCode == TextToSpeech.LANG_NOT_SUPPORTED) { AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言"); } else { //不支持就改成英文 mTTS.setLanguage(Locale.US); } } else { // 检查语音数据是否已下载 if (mTTS.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) { AppLogUtils.e(false, "TTS - onInit", "-----------speakContent " + speakContent); speak(speakContent); } else { AppLogUtils.e(false, " TTS - onInit", "中文语音数据未完整下载。"); } } } /** * TTS初始化之后有时会无法播放语音。 * 从打印日志看failed: not bound to TTS engine * 找到源代码打印处 * if (mServiceConnection == null) { * Log.w(TAG, method + " failed: not bound to TTS engine"); * return errorResult; * } * 通过反射判断mServiceConnection是否为空 * * @param tts * @return true 可用 */ public static boolean ismServiceConnectionUsable(TextToSpeech tts) { boolean isBindConnection = true; if (tts == null) { return false; } Field[] fields = tts.getClass().getDeclaredFields(); for (int j = 0; j < fields.length; j++) { fields[j].setAccessible(true); if (TextUtils.equals("mConnectingServiceConnection", fields[j].getName()) && TextUtils.equals("android.speech.tts.TextToSpeech$Connection", fields[j].getType().getName())) { try { if (fields[j].get(tts) == null) { isBindConnection = false; } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } return isBindConnection; } }