Browse Source

<增加tts语音播报>

weizhengliang 4 years ago
parent
commit
de4a97b332

+ 6 - 1
middleware/src/main/code/com/wdkl/ncs/android/middleware/common/Constants.kt

@@ -23,6 +23,9 @@ class Constants {
         //Interaction ID
         var interactionId: Int? = -1
 
+        //tts服务是否可用: 0-不可用, 1-可用但不支持中文, 2-可用且支持中文
+        var TTS_STATUS = 0
+
         /**
          * TCP消息
          */
@@ -37,6 +40,8 @@ class Constants {
         //刷新呼叫记录
         val EVENT_REFRESH_CALL_LIST = 0x04
 
+        val EVENT_SPEECH = 0x05
+
         //手柄拿起
         val HOOK_OFF = "com.android.PhoneWinowManager.HOOK_OFF"
         //手柄放下
@@ -47,7 +52,7 @@ class Constants {
         //待机
         val CALL_STANDBY = 0
 
-        //呼叫
+        //去电
         val CALL_OUTGOING = 1
 
         //来电中

+ 2 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceChannel.java

@@ -40,6 +40,8 @@ public class DeviceChannel {
             case VOICE:
                 if (tcpModel.getAction()== TcpAction.VoiceAction.CALL){ //语音呼入
                     InteractionVO interactionVO = new Gson().fromJson(tcpModel.getData().toString(), InteractionVO.class);
+                    //有新的呼叫进来,添加到语音播报队列
+                    EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.Companion.getEVENT_SPEECH()));
                     //todo: 判断当前是否通话
                     // 通话中
                     if (calling){

+ 16 - 1
nursehome/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/NurseHomeActivity.kt

@@ -32,6 +32,7 @@ import com.wdkl.core.consts.Urls
 import com.wdkl.core.socket.IUserState
 import com.wdkl.core.socket.SocketManager
 import com.wdkl.core.voip.CallSingleActivity
+import com.wdkl.core.voip.SpeechUtil
 import com.wdkl.ncs.android.component.nursehome.BuildConfig
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.SipUtil.SipCallBack
@@ -166,6 +167,8 @@ class NurseHomeActivity  : BaseActivity<NurseHomeActivityPresenter, ActivityNurs
         initCountDownTimer()
 
         updateNetState()
+
+        SpeechUtil.getInstance().init(this)
     }
 
     /**
@@ -274,6 +277,7 @@ class NurseHomeActivity  : BaseActivity<NurseHomeActivityPresenter, ActivityNurs
         countDownTimer.cancel()
         unregisterReceiver(receiver)
         SocketManager.getInstance().unConnect()
+        SpeechUtil.getInstance().release()
     }
     /**
      *处理错误信息
@@ -691,13 +695,13 @@ fun call(tyte:Int){
                         Constants.fromId = tcpModel.fromId
                         Constants.interactionId = interactionVO.id
                         Constants.CALL_STATE = Constants.CALL_INCOMING
+                        DeviceChannel.calling = true
 
                         CallDialogHelper.dismissCallDialog()
                         CallDialogHelper.showCallDialog(this@NurseHomeActivity, 1, interactionVO.fromFrameFullName, View.OnClickListener {
                             //呼出取消
                         }, View.OnClickListener {
                             //来电接听
-                            DeviceChannel.calling = true
                             VoiceUtil.acceptAudioCall(Integer.parseInt(Constants.ids), Constants.fromId, Constants.interactionId)
                             CallDialogHelper.dismissCallDialog()
                         }, View.OnClickListener {
@@ -772,6 +776,17 @@ fun call(tyte:Int){
                 }
             }
 
+            Constants.EVENT_SPEECH -> {
+                if (Constants.CALL_STATE != Constants.CALL_CALLING) {
+                    if (SettingConfig.getTtsMode(this) == SettingConfig.TTS_ON) {
+                        val tcpModel = messageEvent.getMessage() as TcpModel
+                        val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                        val frameName = interactionVO.fromFrameFullName.replace("-", "")
+                        SpeechUtil.getInstance().addSpeech(frameName + "呼叫", false)
+                    }
+                }
+            }
+
             //TCP连接状态
             Constants.EVENT_TCP_STATE -> {
                 updateTcpState()

+ 28 - 0
nursehome/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SystemSettingsFragment.kt

@@ -12,12 +12,14 @@ import com.enation.javashop.net.engine.model.NetState
 import com.wdkl.ncs.android.component.nursehome.BuildConfig
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.common.Constants
 import com.wdkl.ncs.android.component.nursehome.databinding.FragmentSystemSettingsBinding
 import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.nursehome.util.ScreenManagerUtil
 import com.wdkl.ncs.android.component.nursehome.util.VoiceManagerUtil
 import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SystemSettingsContract
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SystemSettingsPresenter
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
@@ -59,6 +61,16 @@ class SystemSettingsFragment:BaseFragment<SystemSettingsPresenter,FragmentSystem
 //        var endValue = SettingConfig.getEndOfDayLocation(this.activity)
         doubleslide_withoutrule.update(initialValue,endValue)
 
+        if (SettingConfig.TTS_ON == SettingConfig.getTtsMode(this.activity)) {
+            if (Constants.TTS_STATUS == 2) {
+                radio_tts_on.isChecked = true
+            } else {
+                radio_tts_off.isChecked = true
+            }
+        } else {
+            radio_tts_off.isChecked = true
+        }
+
         //todo 这里实际是应该从服务器拿或者本地拿数据显示
         //语音播报次数
         call_number_tv.text = SettingConfig.getCallNumber(this.activity).toString()
@@ -175,6 +187,22 @@ class SystemSettingsFragment:BaseFragment<SystemSettingsPresenter,FragmentSystem
             SettingConfig.setEndOfDay(this.activity,bigTime)
 
         }
+
+        group_tts_set.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_tts_on) {
+                if (Constants.TTS_STATUS == 2) {
+                    showMessage("TTS启用成功")
+                    SettingConfig.setTtsMode(this.activity, SettingConfig.TTS_ON)
+                } else {
+                    showMessage("TTS不可用,请检查是否已经安装TTS服务")
+                    radio_tts_off.isChecked = true
+                    SettingConfig.setTtsMode(this.activity, SettingConfig.TTS_OFF)
+                }
+            } else if (checkedId == R.id.radio_tts_off) {
+                SettingConfig.setTtsMode(this.activity, SettingConfig.TTS_OFF)
+            }
+        }
+
         //播报次数加减
         call_number_decrease_tv.setOnClickListener(this)
         call_number_add_tv.setOnClickListener(this)

+ 17 - 0
nursehome/src/main/java/com/wdkl/ncs/android/component/nursehome/settingconfig/SettingConfig.java

@@ -3,6 +3,8 @@ package com.wdkl.ncs.android.component.nursehome.settingconfig;
 import android.content.Context;
 import android.content.SharedPreferences;
 
+import com.wdkl.core.voip.SpeechUtil;
+
 
 public class SettingConfig {
 
@@ -55,6 +57,12 @@ public class SettingConfig {
     private static final String KEY_SP_HOST_GAMEPAD_PLAY_VOLUME = "KEY_SP_HOST_GAMEPAD_PLAY_VOLUME";
     private static final int host_gamepad_play_volume = 40;
 
+    //语音播报模式
+    private static final String KEY_SP_TTS_MODE = "KEY_SP_TTS_MODE";
+    public static final int TTS_OFF = 0;  //音乐
+    public static final int TTS_ON = 1; //tts语音
+
+
     //通话模式
     private static final String KEY_SP_TALK_MODE = "KEY_SP_TALK_MODE";
     public static final int single_pass_mode = 0;  //单工模式
@@ -107,6 +115,14 @@ public class SettingConfig {
     private static final String KEY_SP_DOOR_PHONE_VOLUME = "KEY_SP_DOOR_PHONE_VOLUME";
     private static final int door_phone_volume = 70;
 
+    //语音播报模式
+    public static int getTtsMode(Context context) {
+        return getSP(context).getInt(KEY_SP_TTS_MODE, TTS_ON);
+    }
+
+    public static void setTtsMode(Context context, int mode) {
+        getEditor(context).putInt(KEY_SP_TTS_MODE, mode).apply();
+    }
 
     /**
      * 获取播报次数
@@ -123,6 +139,7 @@ public class SettingConfig {
      * @param value
      */
     public static void setCallNumber(Context context, int value) {
+        SpeechUtil.getInstance().setSpeechLoopCount(value);
         getEditor(context).putInt(KEY_SP_CALL_NUMBER, value).apply();
     }
 

+ 6 - 1
nursehome/src/main/java/com/wdkl/ncs/android/component/nursehome/util/CallDialogHelper.java

@@ -14,7 +14,9 @@ import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.wdkl.core.voip.AsyncPlayer;
+import com.wdkl.core.voip.SpeechUtil;
 import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
 
 
 public class CallDialogHelper {
@@ -50,7 +52,9 @@ public class CallDialogHelper {
             outCall.setVisibility(View.GONE);
             inCall.setVisibility(View.VISIBLE);
             textName.setText("有新的通话请求: " + name);
-            ringPlayer.play(activity, R.raw.incoming_call, true, AudioManager.STREAM_MUSIC);
+            if (SettingConfig.getTtsMode(activity) == SettingConfig.TTS_OFF) {
+                ringPlayer.play(activity, R.raw.incoming_call, true, AudioManager.STREAM_MUSIC);
+            }
         }
 
         hangup.setOnClickListener(hangupCall);
@@ -82,6 +86,7 @@ public class CallDialogHelper {
             if (ringPlayer != null) {
                 ringPlayer.stop();
             }
+            SpeechUtil.getInstance().stopSpeak();
         }
     }
 }

+ 38 - 0
nursehome/src/main/res/layout/fragment_system_settings.xml

@@ -72,6 +72,44 @@
                     android:paddingLeft="6px">
 
                     <LinearLayout
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="2dp"
+                        android:layout_marginBottom="10px"
+                        android:orientation="horizontal">
+
+                        <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_gravity="center_vertical"
+                            android:text="播报模式:"
+                            android:textColor="#000000"
+                            android:textSize="14px" />
+
+                        <RadioGroup
+                            android:id="@+id/group_tts_set"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:orientation="horizontal">
+
+                            <RadioButton
+                                android:id="@+id/radio_tts_on"
+                                android:layout_width="wrap_content"
+                                android:layout_height="wrap_content"
+                                android:text="TTS"
+                                android:textSize="14px" />
+
+                            <RadioButton
+                                android:id="@+id/radio_tts_off"
+                                android:layout_width="wrap_content"
+                                android:layout_height="wrap_content"
+                                android:text="音乐"
+                                android:textSize="14px" />
+                        </RadioGroup>
+
+                    </LinearLayout>
+
+                    <LinearLayout
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:orientation="horizontal">

BIN
tts/iFlytek.apk


+ 188 - 0
webrtc/src/main/java/com/wdkl/core/voip/SpeechUtil.java

@@ -0,0 +1,188 @@
+package com.wdkl.core.voip;
+
+import android.content.Context;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.nursehome.common.Constants;
+
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class SpeechUtil {
+    private static final String TAG = "SpeechUtil";
+
+    private TextToSpeech textToSpeech;
+    private static SpeechUtil speech;
+    private int speakIndex = 0;
+    private int loopCount = 2;
+    private boolean isStop = true;
+    public volatile static ArrayList<String> speechTextList = new ArrayList<>();
+    private Thread speechThread;
+    private boolean isSpeechLoop = true;
+    private String speakSpeech;
+    private final Object lockObject = new Object();
+
+    public static SpeechUtil getInstance() {
+        if (speech == null) {
+            synchronized (SpeechUtil.class) {
+                if (speech == null) {
+                    speech = new SpeechUtil();
+                }
+            }
+        }
+        return speech;
+    }
+
+    public void init(Context context) {
+        textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+            @Override
+            public void onInit(int status) {
+                if (status == TextToSpeech.SUCCESS) {
+                    int supported = textToSpeech.setLanguage(Locale.CHINESE);
+                    if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
+                        Constants.Companion.setTTS_STATUS(1);
+                        Log.d(TAG, "onInit: 当前不支持中文");
+                    } else {
+                        Constants.Companion.setTTS_STATUS(2);
+                        Log.d(TAG, "onInit: 支持中文");
+                    }
+                    Log.d(TAG, "onInit: TTS引擎初始化成功");
+                } else {
+                    Constants.Companion.setTTS_STATUS(0);
+                    Log.d(TAG, "onInit: TTS引擎初始化失败");
+                }
+            }
+        });
+        textToSpeech.setSpeechRate(0.5f);
+
+    }
+
+    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) {
+                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, null, "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.isSpeaking()) {
+            textToSpeech.stop();
+            isStop = true;
+            speakIndex = 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;
+        }
+    }
+
+    public void startSpeechThread() {
+        if (null == speechThread) {
+            speechThread = new Thread(new SpeechRunnable());
+            speechThread.start();
+        } else if (!speechThread.isAlive()) {
+            speechThread.start();
+        }
+    }
+
+    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);
+                }
+
+                try {
+                    Thread.sleep(50);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+}