MTTSManager.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package com.hanghui.senic.common;
  2. import android.content.Context;
  3. import android.speech.tts.TextToSpeech;
  4. import android.text.TextUtils;
  5. import com.blankj.utilcode.util.LogUtils;
  6. import com.google.gson.Gson;
  7. import com.hanghui.senic.MyAppliction;
  8. import com.hanghui.senic.service.usbserialdemo.utile.MTTSDemo;
  9. import com.hanghui.senic.service.usbserialdemo.utile.StringIsNull;
  10. import com.hanghui.senic.service.usbserialdemo.utile.loacat.AppLogUtils;
  11. import java.lang.reflect.Field;
  12. import java.util.Locale;
  13. /**
  14. * 语音播报
  15. */
  16. public class MTTSManager implements TextToSpeech.OnInitListener {
  17. private static MTTSManager instance;
  18. private TextToSpeech mTTS;
  19. private String speakContent = "";
  20. public MTTSManager() {
  21. if (mTTS == null) {
  22. //监听器就直接传入本类
  23. mTTS = new TextToSpeech(MyAppliction.getContext(), this);
  24. }
  25. }
  26. public static synchronized MTTSManager getInstance() {
  27. if (instance == null) {
  28. instance = new MTTSManager();
  29. }
  30. return instance;
  31. }
  32. public void speak(String text) {
  33. if (StringIsNull.IsStringNull(text)) {
  34. AppLogUtils.e(true, "TTS语音播报", "语音内容为空 ");
  35. return;
  36. }
  37. AppLogUtils.e(false, "TTS语音播报", "TTS语音播报内容 : " + text);
  38. if (ismServiceConnectionUsable(mTTS)) {
  39. if (mTTS == null) {
  40. mTTS = new TextToSpeech(MyAppliction.getContext(), this);
  41. }
  42. speakContent = text;
  43. //设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规
  44. mTTS.setPitch(1.0f);
  45. //设置语速
  46. mTTS.setSpeechRate(1.0f);
  47. //TextToSpeech.QUEUE_ADD添加到队列后面,依次将前面的读完轮序
  48. //TextToSpeech.QUEUE_FLUSH刷新队列,将之前的队列取消阅读现在的文字
  49. mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null);
  50. } else {//被回收了不可用状态
  51. if (mTTS != null){
  52. mTTS.stop();
  53. mTTS.shutdown();
  54. }
  55. mTTS = new TextToSpeech(MyAppliction.getContext(), status -> {
  56. if (status == TextToSpeech.SUCCESS) {
  57. int result = mTTS.setLanguage(Locale.CHINA);
  58. if (result != TextToSpeech.LANG_COUNTRY_AVAILABLE
  59. && result != TextToSpeech.LANG_AVAILABLE) {
  60. AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言");
  61. }
  62. //设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规
  63. mTTS.setPitch(1.0f);
  64. //设置语速
  65. mTTS.setSpeechRate(1.0f);
  66. mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null);
  67. } else {
  68. AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: TTS初始化失败");
  69. }
  70. }, "com.iflytek.speechcloud");//科大讯飞语音引擎
  71. }
  72. }
  73. public void init() {
  74. //监听器就直接传入本类
  75. mTTS = new TextToSpeech(MyAppliction.getContext(), this);
  76. }
  77. public void destroy() {
  78. if (mTTS != null) {
  79. mTTS.stop();
  80. mTTS.shutdown();
  81. mTTS = null;
  82. }
  83. instance = null;
  84. }
  85. @Override
  86. public void onInit(int status) {
  87. if (mTTS == null) {
  88. mTTS = new TextToSpeech(MyAppliction.getContext(), this);
  89. }
  90. //判断是否转化成功
  91. if (status == TextToSpeech.SUCCESS) {
  92. //设置语言为中文
  93. int languageCode = mTTS.setLanguage(Locale.CHINESE);
  94. //判断是否支持这种语言,Android原生不支持中文,使用科大讯飞的tts引擎就可以了
  95. if (languageCode == TextToSpeech.LANG_NOT_SUPPORTED) {
  96. AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言");
  97. } else {
  98. //不支持就改成英文
  99. mTTS.setLanguage(Locale.US);
  100. }
  101. } else {
  102. // 检查语音数据是否已下载
  103. if (mTTS.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) {
  104. AppLogUtils.e(false, "TTS - onInit", "-----------speakContent " + speakContent);
  105. speak(speakContent);
  106. } else {
  107. AppLogUtils.e(false, " TTS - onInit", "中文语音数据未完整下载。");
  108. }
  109. }
  110. }
  111. /**
  112. * TTS初始化之后有时会无法播放语音。
  113. * 从打印日志看failed: not bound to TTS engine
  114. * 找到源代码打印处
  115. * if (mServiceConnection == null) {
  116. * Log.w(TAG, method + " failed: not bound to TTS engine");
  117. * return errorResult;
  118. * }
  119. * 通过反射判断mServiceConnection是否为空
  120. *
  121. * @param tts
  122. * @return true 可用
  123. */
  124. public static boolean ismServiceConnectionUsable(TextToSpeech tts) {
  125. boolean isBindConnection = true;
  126. if (tts == null) {
  127. return false;
  128. }
  129. Field[] fields = tts.getClass().getDeclaredFields();
  130. for (int j = 0; j < fields.length; j++) {
  131. fields[j].setAccessible(true);
  132. if (TextUtils.equals("mConnectingServiceConnection", fields[j].getName()) && TextUtils.equals("android.speech.tts.TextToSpeech$Connection", fields[j].getType().getName())) {
  133. try {
  134. if (fields[j].get(tts) == null) {
  135. isBindConnection = false;
  136. }
  137. } catch (IllegalArgumentException e) {
  138. e.printStackTrace();
  139. } catch (IllegalAccessException e) {
  140. e.printStackTrace();
  141. } catch (Exception e) {
  142. e.printStackTrace();
  143. }
  144. }
  145. }
  146. return isBindConnection;
  147. }
  148. }