@@ -1,25 +1,11 @@
package com.mogo.commons.voice ;
import android.app.ActivityManager ;
import android.content.Context ;
import android.content.Intent ;
import android.content.pm.ApplicationInfo ;
import android.text.TextUtils ;
import com.mogo.commons.AbsMogoApplication ;
import com.mogo.utils.logger.Logger ;
import com.zhidao.auto.platform.voice.VoiceClie nt ;
import com.zhidao.voicesdk.MogoVoiceManager ;
import com.zhidao.voicesdk.MogoVoiceManagerImpl ;
import com.zhidao.voicesdk.callback.OnConnStatusListener ;
import com.zhidao.voicesdk.callback.OnTtsListener ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Map ;
import java.util.concurrent.ConcurrentHashMap ;
import com.alibaba.android.arouter.launcher.ARouter ;
import com.mogo.tts.base.IMogoTTS ;
import com.mogo.tts.base.MogoTTSConsta nts ;
import com.mogo.tts.base.PreemptType ;
/**
* @author congtaowang
@@ -27,14 +13,11 @@ import java.util.concurrent.ConcurrentHashMap;
* <p>
* 语音助手通信助手
*/
public class AIAssist implements VoiceClient . VoiceCmdCallBack , OnTtsListener {
public class AIAssist {
private static final String TAG = " AIAssist " ;
private static volatile AIAssist sInstance ;
private String mLastQAndASpeakText ;
private boolean mHasFlush = false ;
private boolean mInitReady = false ;
private IMogoTTS mTTS ;
public static AIAssist getInstance ( Context context ) {
if ( sInstance = = null ) {
@@ -48,61 +31,15 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
}
public synchronized void release ( ) {
Logger . d ( TAG , " release " ) ;
if ( mCmdMap ! = null & & ! mCmdMap . isEmpty ( ) & & mVoiceClient ! = null ) {
for ( String cmd : mCmdMap . keySet ( ) ) {
mVoiceClient . unRegisterCustomWakeupCmd ( cmd ) ;
}
if ( mTTS ! = null ) {
mTTS . release ( ) ;
}
mQAndAMap . clear ( ) ;
mVoiceClient . release ( ) ;
mSpeakVoiceMap . clear ( ) ;
mCacheUnWakeupCommands . clear ( ) ;
sInstance = null ;
}
private final VoiceClient mVoiceClient ;
private MogoVoiceManager mogoVoiceManager ;
// 免唤醒指令
private Map < String , List < IMogoVoiceCmdCallBack > > mCmdMap = new HashMap < > ( ) ;
// 问答指令
private Map < String , IMogoVoiceCmdCallBack > mQAndAMap = new HashMap < > ( ) ;
// 单独的语音播放
private Map < String , IMogoVoiceCmdCallBack > mSpeakVoiceMap = new HashMap < > ( ) ;
private Map < String , String [ ] > mCacheUnWakeupCommands = new ConcurrentHashMap < > ( ) ;
private AIAssist ( Context context ) {
// private constructor
mVoiceClient = new VoiceClient ( context . getApplicationContext ( ) ) ;
mVoiceClient . setCallBack ( this ) ;
initFlushStatus ( context ) ;
initSpeech ( context ) ;
Logger . w ( TAG , " voice is ready = %s " , mHasFlush ) ;
}
private void initFlushStatus ( Context context ) {
if ( ! mHasFlush ) {
mHasFlush = isVoiceServiceReady ( context ) ;
}
}
/**
* 初始化
*/
private void initSpeech ( Context context ) {
mogoVoiceManager = MogoVoiceManagerImpl . getInstance ( ) ;
mogoVoiceManager . init ( context , new OnConnStatusListener ( ) {
@Override
public void onSuccess ( ) {
mInitReady = true ;
}
@Override
public void onFailed ( ) {
}
} ) ;
mTTS = ( IMogoTTS ) ARouter . getInstance ( ) . build ( MogoTTSConstants . API_PATH ) . navigation ( context . getApplicationContext ( ) ) ;
}
/**
@@ -111,83 +48,10 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @return
*/
public boolean hasFlush ( ) {
return mHasFlush ;
}
@Override
public void onCmdSelected ( String cmd ) {
if ( ! mCmdMap . containsKey ( cmd ) ) {
return ;
}
Logger . d ( TAG , " received command: %s " , cmd ) ;
Iterator < IMogoVoiceCmdCallBack > iterator = null ;
try {
List < IMogoVoiceCmdCallBack > cmdCallBacks = mCmdMap . get ( cmd ) ;
iterator = new ArrayList < > ( cmdCallBacks ) . iterator ( ) ;
} catch ( Exception e ) {
}
while ( iterator ! = null & & iterator . hasNext ( ) ) {
IMogoVoiceCmdCallBack callBack = iterator . next ( ) ;
if ( callBack ! = null ) {
callBack . onCmdSelected ( cmd ) ;
}
}
}
@Override
public void onCmdAction ( String speakText ) {
if ( ! TextUtils . isEmpty ( mLastQAndASpeakText ) ) {
IMogoVoiceCmdCallBack cmdCallBack = mQAndAMap . remove ( mLastQAndASpeakText ) ;
if ( cmdCallBack ! = null ) {
cmdCallBack . onCmdAction ( speakText ) ;
}
}
}
@Override
public void onCmdCancel ( String speakText ) {
if ( ! TextUtils . isEmpty ( mLastQAndASpeakText ) ) {
IMogoVoiceCmdCallBack cmdCallBack = mQAndAMap . remove ( mLastQAndASpeakText ) ;
if ( cmdCallBack ! = null ) {
cmdCallBack . onCmdCancel ( speakText ) ;
}
}
}
@Override
public void onSpeakEnd ( String speakText ) {
if ( mQAndAMap . containsKey ( speakText ) ) {
mLastQAndASpeakText = speakText ;
IMogoVoiceCmdCallBack cmdCallBack = mQAndAMap . get ( speakText ) ;
if ( cmdCallBack ! = null ) {
cmdCallBack . onSpeakEnd ( speakText ) ;
return ;
}
}
IMogoVoiceCmdCallBack callBack = mSpeakVoiceMap . remove ( speakText ) ;
if ( callBack ! = null ) {
callBack . onSpeakEnd ( speakText ) ;
}
}
@Override
public void onSpeakSelectTimeOut ( String speakText ) {
if ( mQAndAMap . containsKey ( speakText ) ) {
if ( TextUtils . equals ( speakText , mLastQAndASpeakText ) ) {
mLastQAndASpeakText = null ;
}
IMogoVoiceCmdCallBack cmdCallBack = mQAndAMap . remove ( speakText ) ;
if ( cmdCallBack ! = null ) {
cmdCallBack . onSpeakSelectTimeOut ( speakText ) ;
return ;
}
}
IMogoVoiceCmdCallBack callBack = mSpeakVoiceMap . remove ( speakText ) ;
if ( callBack ! = null ) {
callBack . onSpeakSelectTimeOut ( speakText ) ;
if ( mTTS ! = null ) {
return mTTS . hasFlush ( ) ;
}
return false ;
}
/**
@@ -196,13 +60,8 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param text
*/
public void speakTTSVoice ( String text , IMogoVoiceCmdCallBack callBack ) {
try {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mSpeakVoiceMap . put ( text , callBack ) ;
mVoiceClient . speakDefault ( text ) ;
}
} catch ( Exception e ) {
if ( mTTS ! = null ) {
mTTS . speakTTSVoice ( text , callBack ) ;
}
}
@@ -212,12 +71,8 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param text
*/
public void speakTTSVoice ( String text ) {
try {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mVoiceClient . speakDefault ( text ) ;
}
} catch ( Exception e ) {
if ( mTTS ! = null ) {
mTTS . speakTTSVoice ( text ) ;
}
}
@@ -228,13 +83,25 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param type 播报策略
*/
public void speakTTSVoice ( String text , VoicePreemptType type , IMogoVoiceCmdCallBack callBack ) {
try {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mSpeakVoiceMap . put ( text , callBack ) ;
mVoiceClient . speakTypeText ( text , type . getPreemptType ( ) ) ;
if ( mTTS ! = null ) {
PreemptType preemptType = PreemptType . PREEMPT_TYPE_NONE ;
if ( type ! = null ) {
switch ( type ) {
case PREEMPT_TYPE_FLUSH :
preemptType = PreemptType . PREEMPT_TYPE_FLUSH ;
break ;
case PREEMPT_TYPE_NEXT :
preemptType = PreemptType . PREEMPT_TYPE_NEXT ;
break ;
case PREEMPT_TYPE_IMMEADIATELY :
preemptType = PreemptType . PREEMPT_TYPE_IMMEDIATELY ;
break ;
case PREEMPT_TYPE_IMMEADIATELY_WITHOUT_CANCLE :
preemptType = PreemptType . PREEMPT_TYPE_IMMEDIATELY_WITHOUT_CANCEL ;
break ;
}
}
} catch ( Exception e ) {
mTTS . speakTTSVoice ( text , preemptType , callBack ) ;
}
}
@@ -244,10 +111,8 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param tts 播报内容
*/
public void speakQAndACmd ( String tts , IMogoVoiceCmdCallBack callBack ) {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mQAndAMap . put ( tts , callBack ) ;
mVoiceClient . speakTtsAndRegistCmd ( tts ) ;
if ( mTTS ! = null ) {
mTTS . speakQAndACmd ( tts , callBack ) ;
}
}
@@ -259,10 +124,8 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param cancelCmds 取消命令唤醒词
*/
public void speakQAndACmd ( String tts , String [ ] okCmds , String [ ] cancelCmds , IMogoVoiceCmdCallBack callBack ) {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mQAndAMap . put ( tts , callBack ) ;
mVoiceClient . speakTtsAndRegistCmd ( tts , okCmds , cancelCmds ) ;
if ( mTTS ! = null ) {
mTTS . speakQAndACmd ( tts , okCmds , cancelCmds , callBack ) ;
}
}
@@ -274,47 +137,9 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param callBack
*/
public void registerUnWakeupCommand ( String cmd , String [ ] cmdWords , IMogoVoiceCmdCallBack callBack ) {
if ( ! mCmdMap . containsKey ( cmd ) ) {
mCmdMap . put ( cmd , new ArrayList < > ( ) ) ;
if ( mTTS ! = null ) {
mTTS . registerUnWakeupCommand ( cmd , cmdWords , callBack ) ;
}
mCmdMap . get ( cmd ) . add ( callBack ) ;
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mVoiceClient . registerCustomWakeupCmd ( cmd , cmdWords ) ;
mCacheUnWakeupCommands . remove ( cmd ) ;
}
Logger . i ( TAG , " cache un wakeup command2. %s " , cmd ) ;
mCacheUnWakeupCommands . put ( cmd , cmdWords ) ;
}
/**
* 注册免唤醒命令
*
* @param cmd
* @param cmdWords
*/
public void registerUnWakeupCommand ( String cmd , String [ ] cmdWords ) {
initFlushStatus ( AbsMogoApplication . getApp ( ) ) ;
if ( mHasFlush ) {
mVoiceClient . registerCustomWakeupCmd ( cmd , cmdWords ) ;
mCacheUnWakeupCommands . remove ( cmd ) ;
}
Logger . i ( TAG , " cache un wakeup command. %s " , cmd ) ;
mCacheUnWakeupCommands . put ( cmd , cmdWords ) ;
}
/**
* 注册免唤醒命令回调
*
* @param cmd
* @param callBack
*/
public synchronized void registerUnWakeupCommandCallback ( String cmd , IMogoVoiceCmdCallBack callBack ) {
if ( ! mCmdMap . containsKey ( cmd ) ) {
mCmdMap . put ( cmd , new ArrayList < > ( ) ) ;
}
mCmdMap . get ( cmd ) . add ( callBack ) ;
}
/**
@@ -323,9 +148,9 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param cmd
*/
public synchronized void unregisterUnWakeupCommand ( String cmd ) {
mCmdMap . remove ( cmd ) ;
mVoiceClient . unR egisterCustom WakeupCm d ( cmd ) ;
mCacheUnWakeupCommands . remove ( cmd ) ;
if ( mTTS ! = null ) {
mTTS . unr egisterUn WakeupComman d ( cmd ) ;
}
}
/**
@@ -334,20 +159,12 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param cmd
*/
public synchronized void unregisterUnWakeupCommand ( String cmd , IMogoVoiceCmdCallBack callBack ) {
if ( mCmdMap . containsKey ( cmd ) ) {
List < IMogoVoiceCmdCallBack > callBacks = mCmdMap . get ( cmd ) ;
if ( callBacks ! = null ) {
callBacks . remove ( callBack ) ;
}
if ( callBacks . isEmpty ( ) ) {
mCmdMap . remove ( cmd ) ;
mVoiceClient . unRegisterCustomWakeupCmd ( cmd ) ;
mCacheUnWakeupCommands . remove ( cmd ) ;
}
if ( mTTS ! = null ) {
mTTS . unregisterUnWakeupCommand ( cmd , callBack ) ;
}
}
public static void startAssistant ( Context context ) {
public void startAssistant ( Context context ) {
startAssistant ( context , 1 ) ;
}
@@ -355,127 +172,33 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* @param context
* @param status window_start_cancel 0 - 结束, 1 - 显示, 2 - 未激活调试进入
*/
public static void startAssistant ( Context context , int status ) {
final Intent intent = new Intent ( ) ;
intent . setFlags ( I nten t. FLAG_INCLUDE_STOPPED_PACKAGES ) ;
intent . setAction ( " pvetec.intent.action.txz.switch " ) ;
intent . putExtra ( " window_start_cancel " , status ) ;
intent . putExtra ( " extra_switch_type " , " window_start_cancel " ) ;
Logger . d ( TAG , " status = %d " , status ) ;
context . sendBroadcast ( intent ) ;
public void startAssistant ( Context context , int status ) {
if ( mTTS ! = null ) {
mTTS . startAIAssist ( co ntex t, status ) ;
}
}
public synchronized void flush ( ) {
if ( mCacheUnWakeupCommands . isEmpty ( ) ) {
return ;
if ( mTTS ! = null ) {
mTTS . flush ( ) ;
}
mHasFlush = true ;
Logger . d ( TAG , " flush cache voice command when voice service ready. " ) ;
final Map < String , String [ ] > tmp = new HashMap < > ( mCacheUnWakeupCommands ) ;
for ( String cmd : tmp . keySet ( ) ) {
registerUnWakeupCommand ( cmd , tmp . get ( cmd ) ) ;
}
}
private boolean isVoiceServiceReady ( Context context ) {
if ( isProcessRunning ( context , getPackageUid ( context , " com.zhidao.speech " ) )
& & isProcessRunning ( context , getPackageUid ( context , " com.zhidao.speech.adapter " ) ) ) {
return true ;
} else if ( isProcessRunning ( context , getPackageUid ( context , " com.txznet.txz " ) ) & & isProcessRunning ( context , getPackageUid ( context , " com.txznet.adapter " ) ) ) {
Logger . d ( TAG , " txz is voiceServiceReady " ) ;
return true ;
}
return false ;
}
// private boolean isRunningTaskExist( Context context, String processName ) {
//// ActivityManager am = ( ActivityManager ) context.getSystemService( Context.ACTIVITY_SERVICE );
//// List< ActivityManager.RunningAppProcessInfo > processList = am.getRunningAppProcesses();
//// for ( ActivityManager.RunningAppProcessInfo info : processList ) {
//// if ( info.processName.equals( processName ) ) {
//// return true;
//// }
//// }
//// return false;
//// }
/**
* 方法描述:判断某一应用是否正在运行
* Created by cafeting on 2017/2/4.
*
* @param context 上下文
* @param packageName 应用的包名
* @return true 表示正在运行, false 表示没有运行
*/
public static boolean isAppRunning ( Context context , String packageName ) {
ActivityManager am = ( ActivityManager ) context . getSystemService ( Context . ACTIVITY_SERVICE ) ;
List < ActivityManager . RunningTaskInfo > list = am . getRunningTasks ( 100 ) ;
if ( list . size ( ) < = 0 ) {
return false ;
}
for ( ActivityManager . RunningTaskInfo info : list ) {
if ( info . baseActivity . getPackageName ( ) . equals ( packageName ) ) {
return true ;
}
}
return false ;
}
//获取已安装应用的 uid, -1 表示未安装此应用或程序异常
public static int getPackageUid ( Context context , String packageName ) {
try {
ApplicationInfo applicationInfo = context . getPackageManager ( ) . getApplicationInfo ( packageName , 0 ) ;
if ( applicationInfo ! = null ) {
return applicationInfo . uid ;
}
} catch ( Exception e ) {
return - 1 ;
}
return - 1 ;
}
/**
* 判断某一 uid 的程序是否有正在运行的进程,即是否存活
* Created by cafeting on 2017/2/4.
*
* @param context 上下文
* @param uid 已安装应用的 uid
* @return true 表示正在运行, false 表示没有运行
*/
public static boolean isProcessRunning ( Context context , int uid ) {
ActivityManager am = ( ActivityManager ) context . getSystemService ( Context . ACTIVITY_SERVICE ) ;
List < ActivityManager . RunningServiceInfo > runningServiceInfos = am . getRunningServices ( 200 ) ;
if ( runningServiceInfos . size ( ) > 0 ) {
for ( ActivityManager . RunningServiceInfo appProcess : runningServiceInfos ) {
if ( uid = = appProcess . uid ) {
return true ;
}
}
}
return false ;
}
public void speakTTSAndDuck ( String text ) {
speakTTSAndDuck ( text , null ) ;
if ( mTTS ! = null ) {
mTTS . speakTTSAndDuck ( text ) ;
}
}
public void speakTTSAndDuck ( String text , IMogoVoiceCmdCallBack callBack ) {
try {
if ( mInitReady ) {
mSpeakVoiceMap . put ( text , callBack ) ;
mogoVoiceManager . toSpeak ( text , - 3 , this ) ;
}
} catch ( Exception e ) {
if ( mTTS ! = null ) {
mTTS . speakTTSAndDuck ( text , callBack ) ;
}
}
public void shutUp ( String ttsId , String text ) {
try {
mSpeakVoiceMap . remove ( text ) ;
mogoVoiceManager . shutUp ( ttsId ) ;
} catch ( Exception e ) {
if ( mTTS ! = null ) {
mTTS . shutUp ( ttsId , text ) ;
}
}
@@ -483,40 +206,15 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack, OnTtsListener {
* 打断上一条正在播报的语音内容, 仅在Speech上生效, TXZ为空实现
* 语音SDK生效版本从1.0.8.4版本起
*/
public void breakOffSpeak ( ) {
mVoiceClient . breakOffSpeak ( ) ;
public void breakOffSpeak ( ) {
if ( mTTS ! = null ) {
mTTS . breakOffSpeak ( ) ;
}
}
public void clearTTSCallback ( String text ) {
try {
mSpeakVoiceMap . remove ( text ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
if ( mTTS ! = null ) {
mTTS . clearTTSCallback ( text ) ;
}
}
@Override
public void onTtsStart ( String ttsId , String text ) {
IMogoVoiceCmdCallBack callBack = mSpeakVoiceMap . get ( text ) ;
if ( callBack ! = null ) {
callBack . onTTSStart ( ttsId , text ) ;
}
}
@Override
public void onTtsFinish ( String ttsId , String text ) {
IMogoVoiceCmdCallBack callBack = mSpeakVoiceMap . remove ( text ) ;
if ( callBack ! = null ) {
callBack . onTTSEnd ( ttsId , text ) ;
}
}
@Override
public void onTtsError ( String ttsId , String text ) {
IMogoVoiceCmdCallBack callBack = mSpeakVoiceMap . remove ( text ) ;
if ( callBack ! = null ) {
callBack . onTTSError ( ttsId , text ) ;
}
}
}