|
@@ -0,0 +1,311 @@
|
|
|
+package com.wdkl.ncs.s433.transbox.utils;
|
|
|
+
|
|
|
+import android.content.Context;
|
|
|
+import android.media.AudioManager;
|
|
|
+import android.os.Build;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.os.PowerManager;
|
|
|
+import android.speech.tts.TextToSpeech;
|
|
|
+import android.speech.tts.UtteranceProgressListener;
|
|
|
+import android.text.TextUtils;
|
|
|
+import android.util.Log;
|
|
|
+
|
|
|
+import com.wdkl.ncs.s433.transbox.common.Constants;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Locale;
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+
|
|
|
+public class SpeechUtil {
|
|
|
+ private static final String TAG = "SpeechUtil";
|
|
|
+
|
|
|
+ private TextToSpeech textToSpeech;
|
|
|
+ private static SpeechUtil speech;
|
|
|
+ private int loopIndex = 0;
|
|
|
+ private int speakIndex = 0;
|
|
|
+ private int loopCount = 3;
|
|
|
+ private boolean isStop = true;
|
|
|
+ public volatile static ArrayList<String> speechTextList = new ArrayList<>();
|
|
|
+ private boolean isSpeechLoop = true;
|
|
|
+ private String speakSpeech;
|
|
|
+ private final Object lockObject = new Object();
|
|
|
+ private Bundle params;
|
|
|
+
|
|
|
+ private final ExecutorService threadPool = Executors.newSingleThreadExecutor();
|
|
|
+ private SpeechRunnable speechRunnable;
|
|
|
+ private PowerManager.WakeLock mWakeLock;
|
|
|
+
|
|
|
+ public static SpeechUtil getInstance() {
|
|
|
+ if (speech == null) {
|
|
|
+ synchronized (SpeechUtil.class) {
|
|
|
+ if (speech == null) {
|
|
|
+ speech = new SpeechUtil();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return speech;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void init(Context context, final TtsCallback callback) {
|
|
|
+ final String language = "zh";
|
|
|
+ //8.0以下版本自动设置tts
|
|
|
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) {
|
|
|
+ if (Locale.CHINESE.getLanguage().equals(language)) {
|
|
|
+ textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
|
|
|
+ @Override
|
|
|
+ public void onInit(int status) {
|
|
|
+ if (status == TextToSpeech.SUCCESS) {
|
|
|
+ int supported = textToSpeech.setLanguage(new Locale(language));
|
|
|
+ if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
|
|
|
+ Constants.TTS_STATUS = 1;
|
|
|
+ Log.d(TAG, "onInit: 当前不支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 2;
|
|
|
+ Log.d(TAG, "onInit: 支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化成功");
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 0;
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化失败");
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, "com.iflytek.speechcloud");
|
|
|
+ } else {
|
|
|
+ textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
|
|
|
+ @Override
|
|
|
+ public void onInit(int status) {
|
|
|
+ if (status == TextToSpeech.SUCCESS) {
|
|
|
+ int supported = textToSpeech.setLanguage(new Locale(language));
|
|
|
+ if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
|
|
|
+ Constants.TTS_STATUS = 1;
|
|
|
+ Log.d(TAG, "onInit: 当前不支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 2;
|
|
|
+ Log.d(TAG, "onInit: 支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(true);
|
|
|
+ }
|
|
|
+ textToSpeech.setSpeechRate(0.9f);
|
|
|
+ }
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化成功");
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 0;
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化失败");
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, "com.google.android.tts");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //8.0以上版本需要手动设置tts
|
|
|
+ textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
|
|
|
+ @Override
|
|
|
+ public void onInit(int status) {
|
|
|
+ if (status == TextToSpeech.SUCCESS) {
|
|
|
+ int supported = textToSpeech.setLanguage(new Locale(language));
|
|
|
+ if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
|
|
|
+ Constants.TTS_STATUS = 1;
|
|
|
+ Log.d(TAG, "onInit: 当前不支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 2;
|
|
|
+ Log.d(TAG, "onInit: 支持" + language);
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(true);
|
|
|
+ }
|
|
|
+ if (!Locale.CHINESE.getLanguage().equals(language)) {
|
|
|
+ textToSpeech.setSpeechRate(0.9f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化成功");
|
|
|
+ } else {
|
|
|
+ Constants.TTS_STATUS = 0;
|
|
|
+ Log.d(TAG, "onInit: TTS引擎初始化失败");
|
|
|
+ if (callback != null) {
|
|
|
+ callback.onInit(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ //textToSpeech.setSpeechRate(0.5f);
|
|
|
+
|
|
|
+ params = new Bundle();
|
|
|
+ params.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_MUSIC);
|
|
|
+
|
|
|
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
|
|
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Speech_tag");
|
|
|
+
|
|
|
+ startSpeechThread();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addSpeech(String text, boolean emergency) {
|
|
|
+ synchronized (lockObject) {
|
|
|
+ Log.d(TAG, "start add text speech: " + text);
|
|
|
+
|
|
|
+ if (speechTextList.contains(text)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Log.d(TAG, "truely add text speech: " + text);
|
|
|
+
|
|
|
+ if (emergency) {
|
|
|
+ stopSpeak();
|
|
|
+ speechTextList.add(0, text);
|
|
|
+ } else {
|
|
|
+ speechTextList.add(text);
|
|
|
+ }
|
|
|
+ //startSpeechThread();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized void speak(final String text) {
|
|
|
+ Log.d(TAG, "tts speak: " + text);
|
|
|
+
|
|
|
+ isStop = false;
|
|
|
+ textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params, "uniqueId");
|
|
|
+ textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
|
|
|
+ @Override
|
|
|
+ public void onStart(String utteranceId) {
|
|
|
+ //LogUtil.d(TAG, "speak onStart..." + utteranceId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onDone(String utteranceId) {
|
|
|
+ speakIndex++;
|
|
|
+ //LogUtil.d(TAG, "speak onDone...index: " + speakIndex + ", loop: " + loopCount);
|
|
|
+ if (speakIndex < loopCount) {
|
|
|
+ //循环播报
|
|
|
+ speak(text);
|
|
|
+ } else {
|
|
|
+ //语音播报完毕
|
|
|
+ speakIndex = 0;
|
|
|
+ isStop = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(String utteranceId) {
|
|
|
+ isStop = true;
|
|
|
+ Log.d(TAG, "speak onError..." + utteranceId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void stopSpeak() {
|
|
|
+ speechTextList.clear();
|
|
|
+ if (textToSpeech != null && textToSpeech.isSpeaking()) {
|
|
|
+ textToSpeech.stop();
|
|
|
+ isStop = true;
|
|
|
+ speakIndex = 0;
|
|
|
+ loopIndex = 0;
|
|
|
+
|
|
|
+ Log.d(TAG, "stop speak");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void removeSpeak(String text) {
|
|
|
+ synchronized (lockObject) {
|
|
|
+ if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(speakSpeech)) {
|
|
|
+ Log.d(TAG, "remove speak: " + text);
|
|
|
+
|
|
|
+ if (text.equals(speakSpeech) && textToSpeech.isSpeaking()) {
|
|
|
+ textToSpeech.stop();
|
|
|
+ speechTextList.remove(text);
|
|
|
+ isStop = true;
|
|
|
+ speakIndex = 0;
|
|
|
+ } else {
|
|
|
+ speechTextList.remove(text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setSpeechLoopCount(int count) {
|
|
|
+ loopCount = count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void release() {
|
|
|
+ speechTextList.clear();
|
|
|
+ isStop = true;
|
|
|
+ speakIndex = 0;
|
|
|
+ if (textToSpeech != null) {
|
|
|
+ textToSpeech.stop();
|
|
|
+ textToSpeech.shutdown();
|
|
|
+ textToSpeech = null;
|
|
|
+ }
|
|
|
+ releaseWakeLock();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void startSpeechThread() {
|
|
|
+ if (null == speechRunnable) {
|
|
|
+ speechRunnable = new SpeechRunnable();
|
|
|
+ }
|
|
|
+
|
|
|
+ acquireWakeLock();
|
|
|
+ threadPool.execute(speechRunnable);
|
|
|
+ }
|
|
|
+
|
|
|
+ public class SpeechRunnable implements Runnable {
|
|
|
+ public void run() {
|
|
|
+ while (isSpeechLoop) {
|
|
|
+ if (speechTextList.size() > 0 && isStop) {
|
|
|
+ /*speakSpeech = speechTextList.get(0);
|
|
|
+ Log.d(TAG, "speakSpeech: " + speakSpeech);
|
|
|
+ speak(speakSpeech);
|
|
|
+ speechTextList.remove(speakSpeech);*/
|
|
|
+
|
|
|
+ //循环播报
|
|
|
+ if (loopIndex >= speechTextList.size()) {
|
|
|
+ loopIndex = 0;
|
|
|
+ }
|
|
|
+ speakSpeech = speechTextList.get(loopIndex);
|
|
|
+
|
|
|
+ Log.d(TAG, "speakSpeech: " + speakSpeech + ", speak loopIndex: " + loopIndex + ", speech size: " + speechTextList.size());
|
|
|
+ speak(speakSpeech);
|
|
|
+
|
|
|
+ loopIndex++;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ Thread.sleep(500);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void acquireWakeLock() {
|
|
|
+ if (mWakeLock != null) {
|
|
|
+ mWakeLock.acquire();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void releaseWakeLock() {
|
|
|
+ if (mWakeLock != null) {
|
|
|
+ mWakeLock.release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public interface TtsCallback {
|
|
|
+ void onInit(boolean success);
|
|
|
+ }
|
|
|
+}
|