跨进程通讯

This commit is contained in:
yangyakun
2026-04-10 17:27:36 +08:00
parent 724fbbadb0
commit 8d5f093355
20 changed files with 671 additions and 160 deletions

View File

@@ -31,6 +31,15 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".TTSService"
android:exported="true"
android:process=":ttsP"
>
<intent-filter>
<action android:name="com.mogo.tts.ttsservice" />
</intent-filter>
</service>
</application>
</manifest>

View File

@@ -5,8 +5,18 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.mogo.tts.common.IMogoTTSCallback
import com.mogo.tts.common.log.TtsLogManager
import kotlin.random.Random
class MainActivity : AppCompatActivity() {
private val ttsManager = TtsManager()
private val TAG = "MainActivity"
private val ranx = Random(10)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@@ -17,10 +27,31 @@ class MainActivity : AppCompatActivity() {
}
findViewById<AppCompatButton>(R.id.actv_test_tts1).setOnClickListener {
TtsManager.speakTTSVoice("此时每个单兵要负责自己的一个视线防区")
//TtsInnerManager.speakTTSVoice("此时每个单兵要负责自己的一个视线防区")
val info = "此时每个单兵要负责自己的一个视线防区${ranx.nextInt()}"
TtsLogManager.d(TAG,"要播放的语音:${info}")
ttsManager.speakTTSVoice(info,object :IMogoTTSCallback{
override fun onSpeakStart(speakText: String?) {
TtsLogManager.d(TAG,"onSpeakStart:${speakText}")
}
override fun onSpeakComple(speakText: String?) {
TtsLogManager.d(TAG,"onSpeakComple:${speakText}")
}
override fun onStopTts(speakText: String?) {
TtsLogManager.d(TAG,"onStopTts:${speakText}")
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
TtsLogManager.d(TAG,"onSpeakError:${speakText}")
}
})
}
findViewById<AppCompatButton>(R.id.actv_test_tts2).setOnClickListener {
TtsManager.stopTTS()
ttsManager.stopTTS()
}
ttsManager.bindService(this)
}
}

View File

@@ -30,7 +30,7 @@ class MoGoApplication : Application() {
}
private fun initTts() {
TtsManager.init(this)
TTSService.start(this)
}

View File

@@ -8,6 +8,6 @@ import android.os.Build
object PhoneUtilsExtend {
fun getDevicesSn(): String {
return Build.getSerial()
return "name"
}
}

View File

@@ -0,0 +1,24 @@
package com.mogo.tts;
import com.mogo.tts.ITTSCallbackBinder;
interface ICoreBinder {
void speakTTSVoice1(String tts);
void speakTTSVoice2(String tts,in ITTSCallbackBinder callback);
void speakTTSVoic3(String tts, int languageType,in ITTSCallbackBinder callback);
void registerTtsListener(String tag,in ITTSCallbackBinder callback);
void unRegisterTtsListener(String tag);
void clearTtsListener();
void stopTts();
void stopTtsByText(String tts);
}

View File

@@ -0,0 +1,10 @@
package com.mogo.tts;
oneway interface ITTSCallbackBinder {
void onSpeakStart(String speakText);
void onSpeakComple(String speakText);
void onStopTts(String speakText);
void onSpeakError(String speakText,String errorMsg);
}

View File

@@ -0,0 +1,254 @@
package com.mogo.tts
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.mogo.tts.common.IMogoTTSCallback
import com.mogo.tts.common.LangTtsEntity
import com.mogo.tts.common.R
import com.mogo.tts.common.log.TtsLogManager
import java.util.concurrent.ConcurrentHashMap
class TTSService : Service() {
private val TAG = "TTSService"
private val globalStart = "global_"
// 🔥 最佳方案ConcurrentHashMap 管理回调key = tagvalue = 回调)
private val callbackMap = ConcurrentHashMap<String, ITTSCallbackBinder>()
private val iCorebinder = object : ICoreBinder.Stub() {
override fun speakTTSVoice1(tts: String?) {
// 防御空字符串
val text = tts?.takeIf { it.isNotEmpty() } ?: return
TtsInnerManager.speakTTSVoice(tts)
}
override fun speakTTSVoice2(tts: String?, callback: ITTSCallbackBinder?) {
// 防御空字符串
val text = tts?.takeIf { it.isNotEmpty() } ?: return
if(callback==null){
TtsInnerManager.speakTTSVoice(tts)
return
}
// 先缓存 callback
callbackMap[text] = callback
TtsInnerManager.speakTTSVoice(tts,object :IMogoTTSCallback{
override fun onSpeakStart(speakText: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakStart(speakText)
}
}
override fun onSpeakComple(speakText: String?){
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakComple(speakText)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
override fun onStopTts(speakText: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onStopTts(speakText)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakError(speakText,errorMsg)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
})
}
override fun speakTTSVoic3(tts: String?, languageType: Int, callback: ITTSCallbackBinder?) {
// 防御空字符串
val text = tts?.takeIf { it.isNotEmpty() } ?: return
if(callback==null){
TtsInnerManager.speakTTSVoice(tts)
return
}
// 先缓存 callback
callbackMap[text] = callback
val langTtsEntity = LangTtsEntity.getLangTtsEntity(tts, languageType)
TtsInnerManager.speakTTSVoice(langTtsEntity,object :IMogoTTSCallback{
override fun onSpeakStart(speakText: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakStart(speakText)
}
}
override fun onSpeakComple(speakText: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakComple(speakText)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
override fun onStopTts(speakText: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onStopTts(speakText)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
val cb = callbackMap[speakText] ?: return
safeCallback {
cb.onSpeakError(speakText,errorMsg)
}
// ✅ 执行完自动销毁 callback
callbackMap.remove(speakText)
}
})
}
override fun registerTtsListener(tag: String?, callback: ITTSCallbackBinder?) {
if(tag.isNullOrEmpty()){
return
}
if(callback==null){
return
}
val key = "${globalStart}${tag}"
callbackMap[key] = callback
}
override fun unRegisterTtsListener(tag: String?) {
if(tag.isNullOrEmpty()){
return
}
val key = "${globalStart}${tag}"
callbackMap.remove(key)
}
override fun clearTtsListener() {
callbackMap.clear()
}
override fun stopTts() {
TtsInnerManager.stopTTS()
}
override fun stopTtsByText(tts: String?) {
// TODO: 如果正在播放直接停止、如果在排队播放从队伍中移除
}
}
companion object{
fun start(context: Context) {
val serviceIntent = Intent(context, TTSService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent)
} else {
context.startService(serviceIntent)
}
}
}
override fun onCreate() {
super.onCreate()
TtsLogManager.d(TAG,"onCreate")
TtsInnerManager.init(applicationContext)
TtsInnerManager.registerTtsListener(object :IMogoTTSCallback{
override fun onSpeakStart(speakText: String?) {
callbackMap.forEach {
if (it.key.startsWith(globalStart)) {
safeCallback {
it.value.onSpeakStart(speakText)
}
}
}
}
override fun onSpeakComple(speakText: String?) {
callbackMap.forEach {
if (it.key.startsWith(globalStart)) {
safeCallback {
it.value.onSpeakComple(speakText)
}
}
}
}
override fun onSpeakError(speakText: String?, errorMsg: String) {
callbackMap.forEach {
if (it.key.startsWith(globalStart)) {
safeCallback {
it.value.onSpeakError(speakText,errorMsg)
}
}
}
}
})
}
override fun onBind(intent: Intent?): IBinder? {
TtsLogManager.d(TAG,"onBind")
return iCorebinder
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
TtsLogManager.d(TAG,"onStartCommand")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (manager != null) {
val nc = NotificationChannel("Voice", "语音服务", NotificationManager.IMPORTANCE_HIGH)
manager.createNotificationChannel(nc)
}
}
val notification: Notification = NotificationCompat.Builder(applicationContext, "Voice")
.setContentTitle("语音服务运行中")
.setSmallIcon(R.drawable.voice_manager_icon)
.build()
startForeground(1, notification)
return START_STICKY
}
override fun onDestroy() {
TtsLogManager.d(TAG,"onDestroy")
super.onDestroy()
TtsInnerManager.unRegisterTtsListener()
TtsInnerManager.release()
}
// 跨进程回调安全工具方法
private inline fun safeCallback(call: () -> Unit) {
try {
call()
} catch (e: Exception) {
TtsLogManager.e(TAG,e.toString(),e)
}
}
}

View File

@@ -0,0 +1,71 @@
package com.mogo.tts
import android.content.Context
import com.mogo.tts.common.IMogoTTS
import com.mogo.tts.common.IMogoTTSCallback
import com.mogo.tts.common.LangTtsEntity
import com.mogo.tts.common.LanguageType
import com.mogo.tts.common.log.TtsLogManager
object TtsInnerManager {
private const val TAG = "TtsManager"
private var mTTS: IMogoTTS? = null
fun init(context: Context) {
try {
// 暂时换成反射,解决死锁问题
var clazz1: Class<*>? = null
try {
// clazz1 = Class.forName("com.mogo.tts.iflytek.offline.IFlyTekOfflineTts")
clazz1 = Class.forName("com.k2fsa.sherpa.onnx.MogoOfflineTTS")
} catch (ignored: Exception) {
}
if (clazz1 != null) {
mTTS = clazz1.getConstructor().newInstance() as IMogoTTS
}
mTTS?.initTts(context)
} catch (e: Exception) {
e.printStackTrace()
TtsLogManager.d(TAG, "TTS 模块初始化异常")
}
}
fun speakTTSVoice(tts: String?) {
if(tts.isNullOrEmpty()) return
speakTTSVoice(tts,null)
}
fun speakTTSVoice(tts: String?, callBack: IMogoTTSCallback?) {
if(tts.isNullOrEmpty()) return
speakTTSVoice(LangTtsEntity(tts, LanguageType.CHINESE), callBack);
}
fun speakTTSVoice(ttsEntity: LangTtsEntity, callBack: IMogoTTSCallback?) {
if(ttsEntity.ttsContent.isEmpty()){
return
}
mTTS?.speakTTSVoice(ttsEntity, callBack)
}
fun registerTtsListener(callback: IMogoTTSCallback) {
mTTS?.registerTtsListener(callback)
}
fun unRegisterTtsListener() {
mTTS?.unRegisterTtsListener()
}
fun stopTTS() {
mTTS?.stopTts()
}
fun release() {
mTTS?.release()
}
}

View File

@@ -1,42 +1,33 @@
package com.mogo.tts
import android.content.ComponentName
import android.content.Context
import com.mogo.tts.common.IGlobalTtsCallback
import com.mogo.tts.common.IMogoTTS
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.Build
import android.os.IBinder
import android.os.RemoteException
import com.elegant.utils.UiThreadHandler
import com.mogo.tts.common.IMogoTTSCallback
import com.mogo.tts.common.LangTtsEntity
import com.mogo.tts.common.LanguageType
import com.mogo.tts.common.log.TtsLogManager
import java.util.concurrent.atomic.AtomicBoolean
object TtsManager {
private const val TAG = "TtsManager"
private var mTTS: IMogoTTS? = null
fun init(context: Context) {
try {
// 暂时换成反射,解决死锁问题
var clazz1: Class<*>? = null
try {
//clazz1 = Class.forName("com.mogo.tts.iflytek.offline.IFlyTekOfflineTts")
clazz1 = Class.forName("com.k2fsa.sherpa.onnx.MogoOfflineTTS")
} catch (ignored: Exception) {
}
if (clazz1 != null) {
mTTS = clazz1.getConstructor().newInstance() as IMogoTTS
}
mTTS?.initTts(context)
} catch (e: Exception) {
e.printStackTrace()
TtsLogManager.d(TAG, "TTS 模块初始化异常")
}
class TtsManager {
companion object {
private const val SERVER_PACKAGE: String = "com.mogo.tts"
}
private val isBind = AtomicBoolean(false)
private val isServiceException = AtomicBoolean(false) //服务绑定成功后出现异常
protected var binder: ICoreBinder? = null
private var context: Context? = null
fun speakTTSVoice(tts: String?) {
if(tts.isNullOrEmpty()) return
speakTTSVoice(tts,null)
speakTTSVoice(LangTtsEntity(tts, LanguageType.CHINESE), null);
}
@@ -49,24 +40,172 @@ object TtsManager {
if(ttsEntity.ttsContent.isEmpty()){
return
}
mTTS?.speakTTSVoice(ttsEntity, callBack)
if(binder!=null){
try {
binder?.speakTTSVoic3(ttsEntity.ttsContent,ttsEntity.getLanguageDef(),object :
ITTSCallbackBinder.Stub() {
override fun onSpeakStart(speakText: String?) {
callBack?.onSpeakStart(speakText)
}
override fun onSpeakComple(speakText: String?) {
callBack?.onSpeakComple(speakText)
}
override fun onStopTts(speakText: String?) {
callBack?.onStopTts(speakText)
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
callBack?.onSpeakError(speakText,errorMsg)
}
})
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
fun registerTtsListener(key: String, callback: IGlobalTtsCallback) {
mTTS?.registerTtsListener(key, callback)
fun registerTtsListener(tag:String,callback: IMogoTTSCallback) {
if(binder!=null){
try {
binder?.registerTtsListener(tag,object :ITTSCallbackBinder.Stub(){
override fun onSpeakStart(speakText: String?) {
callback.onSpeakStart(speakText)
}
override fun onSpeakComple(speakText: String?) {
callback.onSpeakComple(speakText)
}
override fun onStopTts(speakText: String?) {
callback.onStopTts(speakText)
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
callback.onSpeakError(speakText,errorMsg)
}
})
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
fun unRegisterTtsListener(key: String) {
mTTS?.unRegisterTtsListener(key)
fun unRegisterTtsListener(tag: String) {
if(binder!=null){
try {
binder?.unRegisterTtsListener(tag)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
fun stopTTS() {
mTTS?.stopTts()
if(binder!=null){
try {
binder?.stopTts()
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
fun release() {
mTTS?.release()
fun stopTTS(tts:String) {
if(binder!=null){
try {
binder?.stopTtsByText(tts)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
binder = ICoreBinder.Stub.asInterface(service);
}
override fun onServiceDisconnected(name: ComponentName?) {
isServiceException.set(true);
unbind()
delayBind()
}
}
fun bindService(
context: Context,
) {
this.context = context
bindService()
}
private fun bindService() {
context?.let {
if (!isBind.get()) {
if (isServerInstalled()) {
isBind.set(true)
val intent = Intent("com.mogo.tts.ttsservice")
intent.setPackage(SERVER_PACKAGE)
val isSuccess: Boolean =
it.bindService(intent, connection, Context.BIND_AUTO_CREATE)
if (!isSuccess) {
unbind()
}
} else {
}
}
}
}
private fun unbind() {
if (binder != null) {
try {
binder?.clearTtsListener()
} catch (e: RemoteException) {
e.printStackTrace()
}
binder = null
}
context?.let {
if (isBind.get()) {
isBind.set(false)
try {
it.unbindService(connection)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
private fun delayBind() {
if (isServiceException.get()) {
isServiceException.set(false)
UiThreadHandler.postDelayed({
bindService()
}, 4000L)
}
}
private fun isServerInstalled(): Boolean {
context?.let {
val pm: PackageManager = it.getPackageManager()
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
pm.getApplicationInfo(
SERVER_PACKAGE,
PackageManager.ApplicationInfoFlags.of(0)
).enabled
} else {
pm.getApplicationInfo(SERVER_PACKAGE, 0).enabled
}
} catch (e: PackageManager.NameNotFoundException) {
false
}
}
return false
}
}

View File

@@ -1,7 +1,11 @@
package com.mogo.tts.common
interface IGlobalTtsCallback {
fun onTtsSpeakStart()
fun onTtsSpeakStart(speakText: String?)
fun onTtsSpeakEnd()
fun onTtsSpeakEnd(speakText: String?)
fun onTtsSpeakComple(speakText: String?)
fun onTtsSpeakError(speakText: String?, errorMsg: String)
}

View File

@@ -18,9 +18,9 @@ interface IMogoTTS {
*/
void release();
void registerTtsListener(String key, IGlobalTtsCallback callback);
void registerTtsListener(IMogoTTSCallback callback);
void unRegisterTtsListener(String key);
void unRegisterTtsListener();
void speakTTSVoice(LangTtsEntity ttsEntity, IMogoTTSCallback callBack);

View File

@@ -9,46 +9,10 @@ public
*/
interface IMogoTTSCallback {
/**
* 新SDK接口
*
* @param ttsId
* @param tts
*/
@Deprecated
default void onTTSStart( String ttsId, String tts ) {
}
/**
* 新SDK接口
*
* @param ttsId
* @param tts
*/
@Deprecated
default void onTTSEnd( String ttsId, String tts ) {
}
/**
* 新SDK接口
*
* @param ttsId
* @param tts
*/
@Deprecated
default void onTTSError( String ttsId, String tts ) {
}
default void onSpeakStart( String speakText ) {
}
/**
* 语音播报完毕
*
* @param speakText 播报内容
*/
default void onSpeakEnd( String speakText ) {
default void onSpeakComple( String speakText ) {
}
default void onStopTts( String speakText ) {

View File

@@ -0,0 +1,38 @@
package com.mogo.tts.common
data class LangTtsEntity(
var ttsContent: String,
var language: LanguageType
) {
override fun toString(): String {
return "ttsContent is:$ttsContent,language is:${language.langName}"
}
fun getLanguageDef(): Int {
return when (language) {
LanguageType.CHINESE -> LanguageTypeDef.MODE_CHINESE
LanguageType.ENGLISH -> LanguageTypeDef.MODE_ENGLISH
LanguageType.KOREAN -> LanguageTypeDef.MODE_KOREAN
}
}
companion object {
fun getLangTtsEntity(tts: String, languageType: Int): LangTtsEntity {
val languageType = when (languageType) {
LanguageTypeDef.MODE_ENGLISH -> {
LanguageType.ENGLISH
}
LanguageTypeDef.MODE_KOREAN -> {
LanguageType.KOREAN
}
else -> {
LanguageType.CHINESE
}
}
return LangTtsEntity(tts, languageType)
}
}
}

View File

@@ -0,0 +1,14 @@
package com.mogo.tts.common;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.SOURCE)
public @interface LanguageTypeDef{
public static final int MODE_CHINESE = 0;
public static final int MODE_ENGLISH = 1;
public static final int MODE_KOREAN = 2;
}

View File

@@ -1,55 +0,0 @@
package com.mogo.tts.common
data class MultiLangTtsEntity(
private var ttsList: List<LangTtsEntity>
) {
companion object {
private const val TIMEOUT_MILLIS = 60000
}
private val stringBuffer by lazy {
StringBuffer()
}
private var ttsIndex = 0
private var timeStamp: Long = 0
fun ttsNext(): LangTtsEntity? {
return if (ttsIndex in ttsList.indices) {
ttsList[ttsIndex++]
} else {
null
}
}
fun markTime() {
timeStamp = System.currentTimeMillis()
}
fun isTimeout():Boolean {
return timeStamp > 0 && System.currentTimeMillis() - timeStamp >= TIMEOUT_MILLIS
}
override fun toString(): String {
return stringBuffer.let {
it.setLength(0)
ttsList.forEachIndexed { index, langTtsEntity ->
if (index != ttsList.size - 1) {
it.append("${langTtsEntity};")
} else {
it.append(langTtsEntity)
}
}
it.toString()
}
}
}
data class LangTtsEntity(
var ttsContent: String,
var language: LanguageType
) {
override fun toString(): String {
return "ttsContent is:$ttsContent,language is:${language.langName}"
}
}

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.os.Looper;
import com.elegant.utils.UiThreadHandler;
import com.mogo.tts.common.IGlobalTtsCallback;
import com.mogo.tts.common.IMogoTTS;
import com.mogo.tts.common.IMogoTTSCallback;
import com.mogo.tts.common.LangTtsEntity;
@@ -20,7 +19,7 @@ public abstract class BaseMogoTTS implements IMogoTTS {
protected volatile LangTtsEntity curTtsEntity = null;
protected HashMap<String, IMogoTTSCallback> speakVoiceMap = new HashMap<>();
protected HashMap<String, IGlobalTtsCallback> mGlobalTtsCallback = new HashMap<>();
protected IMogoTTSCallback mGlobalTtsCallback = null;
protected String getTAG() {
return "BaseMogoTTS";
@@ -31,14 +30,12 @@ public abstract class BaseMogoTTS implements IMogoTTS {
this.context = context;
}
public void registerTtsListener(String key,IGlobalTtsCallback callback) {
if (!mGlobalTtsCallback.containsKey(key)) {
this.mGlobalTtsCallback.put(key,callback);
}
public void registerTtsListener(IMogoTTSCallback callback) {
this.mGlobalTtsCallback = callback;
}
public void unRegisterTtsListener(String key){
this.mGlobalTtsCallback.remove(key);
public void unRegisterTtsListener(){
this.mGlobalTtsCallback = null;
}
@Override
@@ -59,7 +56,6 @@ public abstract class BaseMogoTTS implements IMogoTTS {
}
protected void speakMultiLangTTS(LangTtsEntity ttsEntity){
this.curTtsEntity = ttsEntity;
// 合成并播放
TtsLogManager.d(getTAG(), "tts准备合成"+ttsEntity);
}
@@ -80,7 +76,7 @@ public abstract class BaseMogoTTS implements IMogoTTS {
if (speakVoiceMap.containsKey(key)) {
IMogoTTSCallback remove = speakVoiceMap.remove(key);
if(remove!=null) {
remove.onStopTts(key);
remove.onStopTts(curTtsEntity.getTtsContent());
}
}
curTtsEntity = null;
@@ -89,31 +85,27 @@ public abstract class BaseMogoTTS implements IMogoTTS {
}
public void onSpeakBegin() {
if(!mGlobalTtsCallback.isEmpty()) {
for (IGlobalTtsCallback callback : mGlobalTtsCallback.values()) {
callback.onTtsSpeakStart();
}
if(mGlobalTtsCallback != null) {
mGlobalTtsCallback.onSpeakStart(curTtsContent);
}
if (curTtsEntity!=null) {
String key = curTtsEntity.toString();
IMogoTTSCallback iMogoTTSCallback = speakVoiceMap.get(key);
if(iMogoTTSCallback!=null){
iMogoTTSCallback.onSpeakStart(key);
iMogoTTSCallback.onSpeakStart(curTtsEntity.getTtsContent());
}
}
}
public void handleCompleteEvent() {
if(!mGlobalTtsCallback.isEmpty()) {
for (IGlobalTtsCallback callback : mGlobalTtsCallback.values()) {
callback.onTtsSpeakEnd();
}
if(mGlobalTtsCallback!=null) {
mGlobalTtsCallback.onSpeakComple(curTtsContent);
}
if (curTtsEntity!=null) {
String key = curTtsEntity.toString();
IMogoTTSCallback iMogoTTSCallback = speakVoiceMap.get(key);
if(iMogoTTSCallback!=null){
iMogoTTSCallback.onSpeakEnd(key);
iMogoTTSCallback.onSpeakComple(curTtsEntity.getTtsContent());
}
}
curTtsEntity = null;
@@ -121,18 +113,19 @@ public abstract class BaseMogoTTS implements IMogoTTS {
}
public void handleErrorEvent(String error) {
if(mGlobalTtsCallback!=null) {
mGlobalTtsCallback.onSpeakError(curTtsContent,error);
}
if (curTtsEntity != null) {
String key = curTtsEntity.toString();
IMogoTTSCallback iMogoTTSCallback = speakVoiceMap.get(key);
if(iMogoTTSCallback!=null){
iMogoTTSCallback.onSpeakError(key,
error);
iMogoTTSCallback.onSpeakError(curTtsEntity.getTtsContent(), error);
}
} else {
IMogoTTSCallback iMogoTTSCallback = speakVoiceMap.get(curTtsContent);
if(iMogoTTSCallback!=null){
iMogoTTSCallback.onSpeakError(curTtsContent,
error);
iMogoTTSCallback.onSpeakError(curTtsContent, error);
}
}
curTtsEntity = null;

View File

@@ -48,4 +48,12 @@ object TtsLogManager {
}
logListener?.writeLog(LogLevel.error,tag,message)
}
@JvmStatic
fun e(tag: String, message: String,tr:Throwable?) {
if(isDebug) {
Log.e(tag, message,tr)
}
logListener?.writeLog(LogLevel.error,tag,message)
}
}

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
</vector>

View File

@@ -129,6 +129,7 @@ class IFlyTekOfflineTts : BaseMogoTTS() {
private fun startSpeak(langTtsEntity: LangTtsEntity?) {
langTtsEntity?.let {
curTtsEntity = it
curTtsContent = it.ttsContent
realSpeak(it.ttsContent)
}

View File

@@ -150,6 +150,7 @@ class MogoOfflineTTS : BaseMogoTTS() {
private fun startSpeak(langTtsEntity: LangTtsEntity?) {
stopTts()
langTtsEntity?.let {
this.curTtsEntity = langTtsEntity;
curTtsContent = it.ttsContent
realSpeak(it.ttsContent)
}