diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt index dbe66b0d48..0b4499c1e7 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt @@ -109,7 +109,7 @@ class DevaToolsProvider : IDevaToolsProvider { iPCReportManager.initServer() BindingCarManager.init(mContext!!) apmEnvProvider.init(if(DebugConfig.isDebug()) "0" else "1", "${ DebugConfig.getNetMode() }", mDockerVersion ?: "") - BadCaseManager.init() + BadCaseManager.init(mContext!!) if (DebugConfig.isDebug()) { SdtManager.init(mContext!!, true, DetectResultImpl()) // 监听弱网 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt index 22bc2a120b..7077e66053 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt @@ -24,11 +24,11 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.util.* +import com.mogo.tts.base.SpeechUtils import com.zhjt.mogo_core_function_devatools.badcase.biz.* import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord import com.zhjt.mogo_core_function_devatools.ext.enqueuePop -import kotlinx.coroutines.* import me.jessyan.autosize.utils.AutoSizeUtils import record_cache.RecordPanelOuterClass @@ -41,8 +41,9 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis @Volatile private var record: AutoPilotRecord? = null - fun init() { + fun init(context: Context) { CallerAutopilotRecordListenerManager.addListener(TAG, this) + SpeechUtils.init(context) } /** diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 7707869bda..ca2f9308c9 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -3,14 +3,22 @@ package com.zhjt.mogo_core_function_devatools.badcase.biz import android.annotation.SuppressLint import android.app.Activity import android.graphics.PixelFormat +import android.os.Bundle import android.os.CountDownTimer import android.os.Handler import android.os.SystemClock import android.util.DisplayMetrics +import android.util.Log import android.view.* import android.widget.CheckBox import android.widget.ImageView import android.widget.TextView +import com.iflytek.cloud.ErrorCode +import com.iflytek.cloud.InitListener +import com.iflytek.cloud.RecognizerListener +import com.iflytek.cloud.RecognizerResult +import com.iflytek.cloud.SpeechError +import com.iflytek.cloud.SpeechRecognizer import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.eagle.core.data.app.AppConfigInfo import com.mogo.eagle.core.data.deva.badcase.BagDescriptionEntity @@ -26,9 +34,12 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.util.AppUtils import com.mogo.eagle.core.utilcode.util.BarUtils +import com.mogo.eagle.core.utilcode.util.JsonParser import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.tts.base.SpeechUtils import com.zhidao.loglib.call.LogInfoManagerFactory import com.zhidao.loglib.upload.OnUploadListener import com.zhidao.loglib.upload.UploadManager @@ -39,9 +50,10 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import com.zhjt.mogo_core_function_devatools.badcase.record.RecordManager import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import org.json.JSONException +import org.json.JSONObject import record_cache.RecordPanelOuterClass import java.io.File -import java.lang.StringBuilder import java.util.* @@ -84,6 +96,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private var audioFileName:String?=null //录音文件名称 private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签 + private var reasonDetail: String ?= null //语音转写 @Volatile private var recordKey: Long = 0 //录制bag包key @Volatile @@ -102,6 +115,14 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private var clickListener: ClickListener? = null + // 语音听写对象 + private var mIat: SpeechRecognizer? = null + + var ret = 0 // 函数调用返回值 + + // 用HashMap存储听写结果 + private val mIatResults: HashMap = LinkedHashMap() + init { initFloatWindow() } @@ -115,6 +136,10 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_initiative_bad_case, null) as View mFloatLayout.setOnTouchListener(this) + // 初始化识别无UI识别对象 + // 使用SpeechRecognizer对象,可根据回调消息自定义界面; + mIat = SpeechRecognizer.createRecognizer(mActivity, mInitListener) + tvInitiativeNum = mFloatLayout.findViewById(R.id.tvInitiativeNum) tvInitiativeTime = mFloatLayout.findViewById(R.id.tvInitiativeTime) tvInitiativeIdentity = mFloatLayout.findViewById(R.id.tvInitiativeIdentity) @@ -172,10 +197,10 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList uploadReason.append("点刹、顿挫") } if(audioStatus){ - audioStatus = !audioStatus - setAudio(audioStatus) + audioStatus = false + setAudio(false) Handler().postDelayed({ - uploadAudio() + uploadAudio() },1000) }else{ uploadAudio() @@ -200,11 +225,91 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } } + /** + * 初始化监听器。 + */ + private val mInitListener = InitListener { code -> + Log.i(TAG, "SpeechRecognizer init() code = $code") + if (code != ErrorCode.SUCCESS) { + ToastUtils.showShort("讯飞语音听写初始化失败,错误码:$code") + } + } + + /** + * 听写监听器。 + */ + private val mRecognizerListener: RecognizerListener = object : RecognizerListener{ + override fun onVolumeChanged(p0: Int, p1: ByteArray?) { + //showTip("当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length); + } + + override fun onBeginOfSpeech() { + // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入 + } + + override fun onEndOfSpeech() { + // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入 + } + + override fun onResult(results: RecognizerResult?, isLast: Boolean) { + results?.let { + printResult(it) + } + } + + override fun onError(p0: SpeechError?) { + // Tips: + // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。 + } + + override fun onEvent(p0: Int, p1: Int, p2: Int, p3: Bundle?) { + // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因 + // 若使用本地能力,会话id为null + // if (SpeechEvent.EVENT_SESSION_ID == eventType) { + // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID); + // Log.d(TAG, "session id =" + sid); + // } + } + + } + + /** + * 显示结果 + */ + private fun printResult(results: RecognizerResult) { + val text: String = JsonParser.parseIatResult(results.resultString) + var sn: String? = null + // 读取json结果中的sn字段 + try { + val resultJson = JSONObject(results.resultString) + sn = resultJson.optString("sn") + } catch (e: JSONException) { + e.printStackTrace() + } + mIatResults[sn!!] = text + val resultBuffer = java.lang.StringBuilder() + for (key in mIatResults.keys) { + resultBuffer.append(mIatResults[key]) + } + Log.i(TAG, "语音内容=$resultBuffer") + reasonDetail = resultBuffer.toString() + } + var countDownTimer: CountDownTimer?=null private fun setAudio(status: Boolean){ if(status){ //开始录音 + mIat?.let { + //清空之前的内容 + mIatResults.clear() + SpeechUtils.setParam(it) + // 不显示听写对话框 + ret = it.startListening(mRecognizerListener) + if (ret != ErrorCode.SUCCESS) { + ToastUtils.showShort("听写失败,错误码:$ret,请点击网址https://www.xfyun.cn/document/error-code查询解决方案") + } + } audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) //更改录音按钮背景 @@ -229,6 +334,8 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList countDownTimer?.start() } }else{ + //停止语音听写 + mIat?.stopListening() //结束倒计时 countDownTimer?.cancel() countDownTimer?.onFinish() @@ -292,7 +399,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList itx["filename"] = recordFileName?:"" //bag包文件地址 itx["filesize"] = "0" //bag包文件大小 itx["key"] = recordKey.toString() //key - itx["reason"] = uploadReason.toString() //采集原因 + itx["reason"] = "$uploadReason 语音内容:$reasonDetail" //采集原因 itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) itx["channel"] = "1" //渠道 @@ -336,7 +443,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList if(receiveTime!=null){ try { uploadStamp=TimeUtils.dateToStamp(receiveTime,"yyyyMMddHHmmss") - }catch (e: Exception){ + }catch (_: Exception){ } } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index 352f678b83..f02aaf7fa5 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -4,15 +4,23 @@ import android.annotation.SuppressLint import android.app.Activity import android.graphics.Color import android.graphics.PixelFormat +import android.os.Bundle import android.os.CountDownTimer import android.os.Handler import android.util.DisplayMetrics +import android.util.Log import android.view.* import android.widget.CheckBox import android.widget.CompoundButton import android.widget.ImageView import android.widget.TextView import com.google.android.flexbox.FlexboxLayout +import com.iflytek.cloud.ErrorCode +import com.iflytek.cloud.InitListener +import com.iflytek.cloud.RecognizerListener +import com.iflytek.cloud.RecognizerResult +import com.iflytek.cloud.SpeechError +import com.iflytek.cloud.SpeechRecognizer import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.eagle.core.data.app.AppConfigInfo import com.mogo.eagle.core.data.deva.badcase.BagDescriptionEntity @@ -27,6 +35,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.util.* import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String +import com.mogo.tts.base.SpeechUtils import com.zhidao.loglib.call.LogInfoManagerFactory import com.zhidao.loglib.upload.OnUploadListener import com.zhjt.mogo_core_function_devatools.R @@ -39,6 +48,8 @@ import com.zhidao.loglib.util.FileUtil import com.zhjt.mogo_core_function_devatools.badcase.BadCaseAnalyticsManager import me.jessyan.autosize.utils.AutoSizeUtils import org.greenrobot.eventbus.EventBus +import org.json.JSONException +import org.json.JSONObject import java.io.File /** @@ -92,6 +103,16 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene private lateinit var flReasonLayout: FlexboxLayout + // 语音听写对象 + private var mIat: SpeechRecognizer? = null + + var ret = 0 // 函数调用返回值 + + // 用HashMap存储听写结果 + private val mIatResults: HashMap = LinkedHashMap() + + private var reasonDetail: String ?= null //语音转写 + init { initFloatWindow() } @@ -104,6 +125,11 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene private fun initFloatWindow(){ mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_passive_bad_case, null) as View mFloatLayout.setOnTouchListener(this) + + // 初始化识别无UI识别对象 + // 使用SpeechRecognizer对象,可根据回调消息自定义界面; + mIat = SpeechRecognizer.createRecognizer(mActivity, mInitListener) + tvPassiveNum = mFloatLayout.findViewById(R.id.tvPassiveNum) tvPassiveTime = mFloatLayout.findViewById(R.id.tvPassiveTime) tvPassiveIdentity = mFloatLayout.findViewById(R.id.tvPassiveIdentity) @@ -163,9 +189,90 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } } + /** + * 初始化监听器。 + */ + private val mInitListener = InitListener { code -> + Log.i(TAG, "SpeechRecognizer init() code = $code") + if (code != ErrorCode.SUCCESS) { + ToastUtils.showShort("讯飞语音听写初始化失败,错误码:$code") + } + } + + /** + * 听写监听器。 + */ + private val mRecognizerListener: RecognizerListener = object : RecognizerListener{ + override fun onVolumeChanged(p0: Int, p1: ByteArray?) { + //showTip("当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length); + } + + override fun onBeginOfSpeech() { + // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入 + } + + override fun onEndOfSpeech() { + // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入 + } + + override fun onResult(results: RecognizerResult?, isLast: Boolean) { + results?.let { + printResult(it) + } + } + + override fun onError(p0: SpeechError?) { + // Tips: + // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。 + } + + override fun onEvent(p0: Int, p1: Int, p2: Int, p3: Bundle?) { + // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因 + // 若使用本地能力,会话id为null + // if (SpeechEvent.EVENT_SESSION_ID == eventType) { + // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID); + // Log.d(TAG, "session id =" + sid); + // } + } + + } + + /** + * 显示结果 + */ + private fun printResult(results: RecognizerResult) { + val text: String = JsonParser.parseIatResult(results.resultString) + var sn: String? = null + // 读取json结果中的sn字段 + try { + val resultJson = JSONObject(results.resultString) + sn = resultJson.optString("sn") + } catch (e: JSONException) { + e.printStackTrace() + } + mIatResults[sn!!] = text + val resultBuffer = java.lang.StringBuilder() + for (key in mIatResults.keys) { + resultBuffer.append(mIatResults[key]) + } + Log.i(TAG, "语音内容=$resultBuffer") + reasonDetail = resultBuffer.toString() + } + + private fun setAudio(status: Boolean){ if(status){ //开始录音 + mIat?.let { + //清空之前的内容 + mIatResults.clear() + SpeechUtils.setParam(it) + // 不显示听写对话框 + ret = it.startListening(mRecognizerListener) + if (ret != ErrorCode.SUCCESS) { + ToastUtils.showShort("听写失败,错误码:$ret,请点击网址https://www.xfyun.cn/document/error-code查询解决方案") + } + } audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) //更改录音按钮背景 @@ -190,6 +297,8 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene countDownTimer?.start() } }else{ + //停止语音听写 + mIat?.stopListening() //结束倒计时 countDownTimer?.cancel() countDownTimer?.onFinish() @@ -253,7 +362,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene itx["filename"] = recordFileName?:"" //bag包文件地址 itx["filesize"] = "0" //bag包文件大小 itx["key"] = recordKey?:"" //key - itx["reason"] = uploadReason //采集原因 + itx["reason"] = "$uploadReason 语音内容:$reasonDetail" //采集原因 itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) itx["channel"] = "0" //渠道 diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/JsonParser.java b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/JsonParser.java new file mode 100644 index 0000000000..84c48ee7fd --- /dev/null +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/JsonParser.java @@ -0,0 +1,173 @@ +package com.mogo.eagle.core.utilcode.util; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; + +/** + * Json结果解析类 + */ +public class JsonParser { + + public static String parseIatResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + // 转写结果词,默认使用第一个结果 + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + JSONObject obj = items.getJSONObject(0); + ret.append(obj.getString("w")); +// 如果需要多候选结果,解析数组其他字段 +// for(int j = 0; j < items.length(); j++) +// { +// JSONObject obj = items.getJSONObject(j); +// ret.append(obj.getString("w")); +// } + } + } catch (Exception e) { + e.printStackTrace(); + } + return ret.toString(); + } + + public static String parseGrammarResult(String json, String engType) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + // 云端和本地结果分情况解析 + if ("cloud".equals(engType)) { + for (int i = 0; i < words.length(); i++) { + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + for (int j = 0; j < items.length(); j++) { + JSONObject obj = items.getJSONObject(j); + if (obj.getString("w").contains("nomatch")) { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append("【结果】" + obj.getString("w")); + ret.append("【置信度】" + obj.getInt("sc")); + ret.append("\n"); + } + } + } else if ("local".equals(engType)) { + ret.append("【结果】"); + for (int i = 0; i < words.length(); i++) { + JSONObject wsItem = words.getJSONObject(i); + JSONArray items = wsItem.getJSONArray("cw"); + if ("".equals(wsItem.getString("slot"))) { + // 可能会有多个联系人供选择,用中括号括起来,这些候选项具有相同的置信度 + ret.append("【"); + for (int j = 0; j < items.length(); j++) { + JSONObject obj = items.getJSONObject(j); + if (obj.getString("w").contains("nomatch")) { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append(obj.getString("w")).append("|"); + } + ret.setCharAt(ret.length() - 1, '】'); + } else { + //本地多候选按照置信度高低排序,一般选取第一个结果即可 + JSONObject obj = items.getJSONObject(0); + if (obj.getString("w").contains("nomatch")) { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append(obj.getString("w")); + } + } + ret.append("【置信度】" + joResult.getInt("sc")); + ret.append("\n"); + } + + } catch (Exception e) { + e.printStackTrace(); + ret.append("没有匹配结果."); + } + return ret.toString(); + } + + public static String parseGrammarResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + for (int j = 0; j < items.length(); j++) { + JSONObject obj = items.getJSONObject(j); + if (obj.getString("w").contains("nomatch")) { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append("【结果】" + obj.getString("w")); + ret.append("【置信度】" + obj.getInt("sc")); + ret.append("\n"); + } + } + } catch (Exception e) { + e.printStackTrace(); + ret.append("没有匹配结果."); + } + return ret.toString(); + } + + public static String parseLocalGrammarResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + for (int j = 0; j < items.length(); j++) { + JSONObject obj = items.getJSONObject(j); + if (obj.getString("w").contains("nomatch")) { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append("【结果】" + obj.getString("w")); + ret.append("\n"); + } + } + ret.append("【置信度】" + joResult.optInt("sc")); + + } catch (Exception e) { + e.printStackTrace(); + ret.append("没有匹配结果."); + } + return ret.toString(); + } + + public static String parseTransResult(String json, String key) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + String errorCode = joResult.optString("ret"); + if (!errorCode.equals("0")) { + return joResult.optString("errmsg"); + } + JSONObject transResult = joResult.optJSONObject("trans_result"); + ret.append(transResult.optString(key)); + /*JSONArray words = joResult.getJSONArray("results"); + for (int i = 0; i < words.length(); i++) { + JSONObject obj = words.getJSONObject(i); + ret.append(obj.getString(key)); + }*/ + } catch (Exception e) { + e.printStackTrace(); + } + return ret.toString(); + } +} diff --git a/tts/tts-base/build.gradle b/tts/tts-base/build.gradle index 9202b19a5a..bb0c3e8eba 100644 --- a/tts/tts-base/build.gradle +++ b/tts/tts-base/build.gradle @@ -42,10 +42,16 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) + api fileTree(dir: "libs", include: ["*.jar"]) implementation rootProject.ext.dependencies.androidxappcompat implementation rootProject.ext.dependencies.arouter diff --git a/tts/tts-base/libs/Msc.jar b/tts/tts-base/libs/Msc.jar new file mode 100644 index 0000000000..f3375c7973 Binary files /dev/null and b/tts/tts-base/libs/Msc.jar differ diff --git a/tts/tts-base/libs/arm64-v8a/libmsc.so b/tts/tts-base/libs/arm64-v8a/libmsc.so new file mode 100644 index 0000000000..a5d35230cb Binary files /dev/null and b/tts/tts-base/libs/arm64-v8a/libmsc.so differ diff --git a/tts/tts-base/libs/armeabi-v7a/libmsc.so b/tts/tts-base/libs/armeabi-v7a/libmsc.so new file mode 100644 index 0000000000..3aff9a35d8 Binary files /dev/null and b/tts/tts-base/libs/armeabi-v7a/libmsc.so differ diff --git a/tts/tts-base/src/main/java/com/mogo/tts/base/SpeechUtils.kt b/tts/tts-base/src/main/java/com/mogo/tts/base/SpeechUtils.kt new file mode 100644 index 0000000000..a3c8ce95b3 --- /dev/null +++ b/tts/tts-base/src/main/java/com/mogo/tts/base/SpeechUtils.kt @@ -0,0 +1,52 @@ +package com.mogo.tts.base + +import android.content.Context +import com.iflytek.cloud.Setting +import com.iflytek.cloud.SpeechConstant +import com.iflytek.cloud.SpeechRecognizer +import com.iflytek.cloud.SpeechUtility + +object SpeechUtils { + + private var mscInitialize: Boolean =false + + fun init(context: Context){ + if(mscInitialize) + return + // 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null + // 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton + // 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true" + // 参数间使用半角“,”分隔。 + // 设置你申请的应用appid,请勿在'='与appid之间添加空格及空转义符 + // 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误 + SpeechUtility.createUtility(context, "appid=0c498b42") + // 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印 + + // 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印 + Setting.setShowLog(true) + mscInitialize = true + } + + /** + * 参数设置 + */ + fun setParam(mIat: SpeechRecognizer) { + // 清空参数 + mIat.setParameter(SpeechConstant.PARAMS, null) + // 设置听写引擎 + mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD) + // 设置返回结果格式 + mIat.setParameter(SpeechConstant.RESULT_TYPE, "json") + // 设置语言 + mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn") + //此处用于设置dialog中不显示错误码信息 + //mIat.setParameter("view_tips_plain","false"); + // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理 + mIat.setParameter(SpeechConstant.VAD_BOS, "50000") + // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音 + mIat.setParameter(SpeechConstant.VAD_EOS, "10000") + // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点 + mIat.setParameter(SpeechConstant.ASR_PTT, "0") + } + +} \ No newline at end of file diff --git a/tts/tts-iflytek/libs/Msc.jar b/tts/tts-iflytek/libs/Msc.jar deleted file mode 100644 index fe502fb3e5..0000000000 Binary files a/tts/tts-iflytek/libs/Msc.jar and /dev/null differ diff --git a/tts/tts-iflytek/src/main/java/com/mogo/tts/iflytek/IFlyTekTts.kt b/tts/tts-iflytek/src/main/java/com/mogo/tts/iflytek/IFlyTekTts.kt index ac856c092b..91a16feebb 100644 --- a/tts/tts-iflytek/src/main/java/com/mogo/tts/iflytek/IFlyTekTts.kt +++ b/tts/tts-iflytek/src/main/java/com/mogo/tts/iflytek/IFlyTekTts.kt @@ -44,14 +44,7 @@ class IFlyTekTts : IMogoTTS, InitListener { override fun init(context: Context) { this.context = context - - // 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null - // 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton - // 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true" - // 参数间使用半角“,”分隔。 - // 设置你申请的应用appid,请勿在'='与appid之间添加空格及空转义符 - // 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误 - SpeechUtility.createUtility(context, "appid=0c498b42") + SpeechUtils.init(context) ttsEngine = SpeechSynthesizer.createSynthesizer(context, this) updateTtsParam() voicerEntries = context.resources?.getStringArray(R.array.voicer_cloud_values) diff --git a/tts/tts-iflytek/src/main/jniLibs/arm64-v8a/libmsc.so b/tts/tts-iflytek/src/main/jniLibs/arm64-v8a/libmsc.so deleted file mode 100644 index 6a8f3f8862..0000000000 Binary files a/tts/tts-iflytek/src/main/jniLibs/arm64-v8a/libmsc.so and /dev/null differ