[8.0.0]
[fea] [唤醒 线程调整]
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="@dimen/dp_200"
|
android:layout_width="@dimen/dp_200"
|
||||||
android:layout_height="@dimen/dp_580"
|
android:layout_height="@dimen/dp_680"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:background="@drawable/biz_login_error_info">
|
android:background="@drawable/biz_login_error_info">
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
|||||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI_P
|
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI_P
|
||||||
import com.mogo.eagle.core.utilcode.util.DeviceUtils
|
|
||||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
|
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
|
||||||
import com.mogo.map.listener.IMogoMapListener
|
import com.mogo.map.listener.IMogoMapListener
|
||||||
|
import com.mogo.mgintelligent.speech.iflytek.WakeUpManager
|
||||||
import com.mogo.och.common.module.biz.provider.CommonService
|
import com.mogo.och.common.module.biz.provider.CommonService
|
||||||
import com.mogo.och.common.module.constant.OchCommonConst
|
import com.mogo.och.common.module.constant.OchCommonConst
|
||||||
import com.mogo.och.common.module.manager.xiaozhi.ZhiStateManager
|
import com.mogo.och.common.module.manager.xiaozhi.ZhiStateManager
|
||||||
@@ -135,6 +135,12 @@ class TaxiPassengerBaseFragment :
|
|||||||
settingAndMusicListener()
|
settingAndMusicListener()
|
||||||
bottom.setOverMapApplyClick(object : BottomBar.ApplyClickLintener{
|
bottom.setOverMapApplyClick(object : BottomBar.ApplyClickLintener{
|
||||||
override fun onApplyClick(selectItem: BottomBar.SelectView) {
|
override fun onApplyClick(selectItem: BottomBar.SelectView) {
|
||||||
|
CallerLogger.d(TAG,"选择的项:${selectItem}")
|
||||||
|
if(selectItem==BottomBar.SelectView.PRECISIONMAP){
|
||||||
|
WakeUpManager.startWakeUp()
|
||||||
|
}else{
|
||||||
|
WakeUpManager.stopWakeup()
|
||||||
|
}
|
||||||
when (selectItem) {
|
when (selectItem) {
|
||||||
BottomBar.SelectView.PRECISIONMAP -> {
|
BottomBar.SelectView.PRECISIONMAP -> {
|
||||||
CallerHmiViewControlListenerManager.invokeMainPageViewVisible(View.VISIBLE)
|
CallerHmiViewControlListenerManager.invokeMainPageViewVisible(View.VISIBLE)
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import com.mogo.mgintelligent.speech.AsrResult
|
|||||||
import com.mogo.mgintelligent.speech.AsrState
|
import com.mogo.mgintelligent.speech.AsrState
|
||||||
import com.mogo.mgintelligent.speech.IWakeUpListener
|
import com.mogo.mgintelligent.speech.IWakeUpListener
|
||||||
import com.mogo.mgintelligent.speech.MGSpeech
|
import com.mogo.mgintelligent.speech.MGSpeech
|
||||||
import com.mogo.mgintelligent.speech.iflytek.WakeManager
|
|
||||||
import com.mogo.mgintelligent.speech.iflytek.WakeUpListener
|
import com.mogo.mgintelligent.speech.iflytek.WakeUpListener
|
||||||
|
import com.mogo.mgintelligent.speech.iflytek.WakeUpManager
|
||||||
import com.mogo.och.bridge.autopilot.location.OchLocationManager
|
import com.mogo.och.bridge.autopilot.location.OchLocationManager
|
||||||
import com.mogo.och.data.taxi.BaseOrderBean
|
import com.mogo.och.data.taxi.BaseOrderBean
|
||||||
import com.mogo.och.data.taxi.TaxiOrderStatusEnum
|
import com.mogo.och.data.taxi.TaxiOrderStatusEnum
|
||||||
@@ -86,7 +86,7 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
|
|||||||
private val wakeUpListener = object :WakeUpListener{
|
private val wakeUpListener = object :WakeUpListener{
|
||||||
override fun wakeupSuccess() {
|
override fun wakeupSuccess() {
|
||||||
onWakeUp()
|
onWakeUp()
|
||||||
WakeManager.stopWakeup()
|
WakeUpManager.stopWakeup()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
|
|||||||
OrderModel.setOrderStatusCallback(TAG,orderListener)
|
OrderModel.setOrderStatusCallback(TAG,orderListener)
|
||||||
OchLocationManager.addGCJ02Listener(TAG,1,locationCallback)
|
OchLocationManager.addGCJ02Listener(TAG,1,locationCallback)
|
||||||
AIMessageManager.registerListener(this)
|
AIMessageManager.registerListener(this)
|
||||||
WakeManager.setWakeUpListener(wakeUpListener)
|
WakeUpManager.setWakeUpListener(wakeUpListener)
|
||||||
mgSpeech.weakUpListener = this
|
mgSpeech.weakUpListener = this
|
||||||
mgSpeech.startWeakUp()
|
mgSpeech.startWeakUp()
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
|
|||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
AIMessageManager.unregisterListener(this)
|
AIMessageManager.unregisterListener(this)
|
||||||
mgSpeech.weakUpListener = null
|
mgSpeech.weakUpListener = null
|
||||||
WakeManager.setWakeUpListener(null)
|
WakeUpManager.setWakeUpListener(null)
|
||||||
mgSpeech.stopWeakUp()
|
mgSpeech.stopWeakUp()
|
||||||
llmResultJob?.cancel()
|
llmResultJob?.cancel()
|
||||||
OrderModel.setOrderStatusCallback(TAG,null)
|
OrderModel.setOrderStatusCallback(TAG,null)
|
||||||
@@ -240,7 +240,7 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsrState.STATE_EXIT -> {
|
AsrState.STATE_EXIT -> {
|
||||||
WakeManager.startWakeUp()
|
WakeUpManager.startWakeUp()
|
||||||
_asrUIStateFlow.value = AsrUIState.Idle
|
_asrUIStateFlow.value = AsrUIState.Idle
|
||||||
mgSpeech.speak(tipsExit)
|
mgSpeech.speak(tipsExit)
|
||||||
mgSpeech.isAssistantShow(false)
|
mgSpeech.isAssistantShow(false)
|
||||||
|
|||||||
@@ -15,15 +15,10 @@ import androidx.lifecycle.findViewTreeLifecycleOwner
|
|||||||
import androidx.lifecycle.findViewTreeViewModelStoreOwner
|
import androidx.lifecycle.findViewTreeViewModelStoreOwner
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.mogo.eagle.core.data.autopilot.pnc.PncActionsHelper
|
|
||||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningActionsListener
|
|
||||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener.Companion.STATUS_AUTOPILOT_RUNNING
|
|
||||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
|
||||||
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
|
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
|
||||||
import com.mogo.eagle.core.utilcode.kotlin.onClick
|
import com.mogo.eagle.core.utilcode.kotlin.onClick
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
|
import com.mogo.mgintelligent.speech.iflytek.WakeUpManager
|
||||||
import com.mogo.mgintelligent.speech.iflytek.WakeManager
|
|
||||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||||
import com.mogo.och.common.module.utils.BigFrameAnimatorContainer
|
import com.mogo.och.common.module.utils.BigFrameAnimatorContainer
|
||||||
import com.mogo.och.common.module.utils.RxUtils
|
import com.mogo.och.common.module.utils.RxUtils
|
||||||
@@ -42,8 +37,6 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import mogo.telematics.pad.MessagePad
|
|
||||||
import mogo.telematics.pad.MessagePad.DrivingState.USING_RSI_LINK_VALUE
|
|
||||||
|
|
||||||
class AiView @JvmOverloads constructor(
|
class AiView @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -170,11 +163,6 @@ class AiView @JvmOverloads constructor(
|
|||||||
super.onVisibilityAggregated(isVisible)
|
super.onVisibilityAggregated(isVisible)
|
||||||
CallerLogger.d(TAG,"是否展示中:${isVisible}")
|
CallerLogger.d(TAG,"是否展示中:${isVisible}")
|
||||||
try {
|
try {
|
||||||
if(isVisible){
|
|
||||||
WakeManager.startWakeUp()
|
|
||||||
}else{
|
|
||||||
WakeManager.stopWakeup()
|
|
||||||
}
|
|
||||||
if(isVisible){
|
if(isVisible){
|
||||||
aiAnimator?.start()
|
aiAnimator?.start()
|
||||||
RxUtils.createSubscribe(3_000) {
|
RxUtils.createSubscribe(3_000) {
|
||||||
@@ -202,6 +190,7 @@ class AiView @JvmOverloads constructor(
|
|||||||
) {
|
) {
|
||||||
CallerLogger.d(TAG,"${tName()} onTransitionCompleted:${motionLayout?.id}_$currentId")
|
CallerLogger.d(TAG,"${tName()} onTransitionCompleted:${motionLayout?.id}_$currentId")
|
||||||
rvMessagesEmpty.visibility = View.VISIBLE
|
rvMessagesEmpty.visibility = View.VISIBLE
|
||||||
|
WakeUpManager.startWakeUp()
|
||||||
startContextInfo()
|
startContextInfo()
|
||||||
startListInfo()
|
startListInfo()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,12 +62,6 @@ class StatusBarView @JvmOverloads constructor(
|
|||||||
LayoutInflater.from(context).inflate(R.layout.taxt_u_p_statusview, this, true)
|
LayoutInflater.from(context).inflate(R.layout.taxt_u_p_statusview, this, true)
|
||||||
isClickable = true
|
isClickable = true
|
||||||
isFocusable = true
|
isFocusable = true
|
||||||
textClockDate.onClick {
|
|
||||||
WakeManager.startWakeUp()
|
|
||||||
}
|
|
||||||
bcsv_status.onClick {
|
|
||||||
WakeManager.stopWakeup()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.mogo.mgintelligent.speech" >
|
package="com.mogo.mgintelligent.speech" >
|
||||||
|
|
||||||
|
<uses-sdk tools:overrideLibrary="com.bun.miitmdid" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,63 +1,23 @@
|
|||||||
package com.mogo.mgintelligent.speech.iflytek
|
package com.mogo.mgintelligent.speech.iflytek
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.media.AudioFormat
|
|
||||||
import android.media.AudioRecord
|
|
||||||
import android.media.MediaRecorder
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.ActivityCompat
|
|
||||||
import com.iflytek.aikit.core.AiAudio
|
|
||||||
import com.iflytek.aikit.core.AiHandle
|
|
||||||
import com.iflytek.aikit.core.AiHelper
|
import com.iflytek.aikit.core.AiHelper
|
||||||
import com.iflytek.aikit.core.AiListener
|
|
||||||
import com.iflytek.aikit.core.AiRequest
|
|
||||||
import com.iflytek.aikit.core.AiResponse
|
|
||||||
import com.iflytek.aikit.core.AiStatus
|
|
||||||
import com.iflytek.aikit.core.BaseLibrary
|
import com.iflytek.aikit.core.BaseLibrary
|
||||||
import com.iflytek.aikit.core.CoreListener
|
import com.iflytek.aikit.core.CoreListener
|
||||||
import com.iflytek.aikit.core.ErrType
|
import com.iflytek.aikit.core.ErrType
|
||||||
import com.iflytek.aikit.core.LogLvl
|
import com.iflytek.aikit.core.LogLvl
|
||||||
import com.mogo.commons.AbsMogoApplication
|
import com.mogo.commons.AbsMogoApplication
|
||||||
import com.mogo.eagle.core.function.call.setting.CallerRequestActivityHandleManager
|
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||||
import com.mogo.eagle.core.utilcode.util.FileUtils
|
import com.mogo.eagle.core.utilcode.util.FileUtils
|
||||||
import com.mogo.eagle.core.utilcode.util.ResourceUtils
|
import com.mogo.eagle.core.utilcode.util.ResourceUtils
|
||||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||||
import com.mogo.eagle.core.utilcode.util.Utils
|
import com.mogo.eagle.core.utilcode.util.Utils
|
||||||
import java.io.BufferedWriter
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.OutputStreamWriter
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.log10
|
|
||||||
|
|
||||||
object WakeManager {
|
object WakeManager {
|
||||||
|
|
||||||
private val TAG = "WakeManager"
|
private const val TAG = "WakeManager"
|
||||||
|
|
||||||
private const val ABILITYID: String = "e867a88f2"
|
|
||||||
|
|
||||||
private val weakupKey = "你好小智,小智小智,小智你好"
|
|
||||||
|
|
||||||
private val isEnd = AtomicBoolean(true)
|
|
||||||
|
|
||||||
//录音是否在进行
|
|
||||||
private val isRecording = AtomicBoolean(false)
|
|
||||||
|
|
||||||
private var aiHandle: AiHandle? = null
|
|
||||||
|
|
||||||
private var audioRecord: AudioRecord? = null
|
|
||||||
|
|
||||||
private var _wakeUpListener:WakeUpListener?=null
|
|
||||||
|
|
||||||
//录音缓冲区大小
|
|
||||||
private const val BUFFER_SIZE = 1280
|
|
||||||
|
|
||||||
private val coreListener = CoreListener { type, code ->
|
private val coreListener = CoreListener { type, code ->
|
||||||
Log.i(TAG, "core listener code:$code")
|
Log.i(TAG, "core listener code:$code")
|
||||||
@@ -66,10 +26,10 @@ object WakeManager {
|
|||||||
ErrType.AUTH -> {
|
ErrType.AUTH -> {
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
Log.i(TAG, "SDK授权成功")
|
Log.i(TAG, "SDK授权成功")
|
||||||
|
WakeUpManager.startThread()
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "SDK授权失败,授权码为:$code")
|
Log.i(TAG, "SDK授权失败,授权码为:$code")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrType.HTTP -> Log.i(TAG, "SDK状态:HTTP认证结果$code")
|
ErrType.HTTP -> Log.i(TAG, "SDK状态:HTTP认证结果$code")
|
||||||
@@ -79,258 +39,6 @@ object WakeManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWakeUpListener(wakeUpListener:WakeUpListener?){
|
|
||||||
this._wakeUpListener = wakeUpListener
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startWakeUp(){
|
|
||||||
ThreadUtils.getIoPool().submit {
|
|
||||||
// 检测权限
|
|
||||||
val granted = ActivityCompat.checkSelfPermission(AbsMogoApplication.getApp(),
|
|
||||||
Manifest.permission.RECORD_AUDIO)
|
|
||||||
if(granted != PackageManager. PERMISSION_GRANTED){
|
|
||||||
CallerRequestActivityHandleManager.requestPermission(TAG,Manifest.permission.RECORD_AUDIO)
|
|
||||||
return@submit
|
|
||||||
}
|
|
||||||
AiHelper.getInst().registerListener(ABILITYID, edListener)
|
|
||||||
CallerLogger.d(TAG,"START")
|
|
||||||
val ret = start()
|
|
||||||
if (ret == 0) {
|
|
||||||
createAudioRecord() //创建录音器
|
|
||||||
isRecording.set(true)
|
|
||||||
audioRecord?.startRecording() //录音器启动录音
|
|
||||||
|
|
||||||
writeRecording(AiStatus.BEGIN)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stopWakeup(){
|
|
||||||
if(!isEnd.get()) {
|
|
||||||
writeRecording(AiStatus.END)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 能力监听回调
|
|
||||||
*/
|
|
||||||
private val edListener: AiListener = object : AiListener {
|
|
||||||
override fun onResult(handleID: Int, outputData: List<AiResponse>, usrContext: Any?) {
|
|
||||||
if (null != outputData && outputData.size > 0) {
|
|
||||||
for (i in outputData.indices) {
|
|
||||||
CallerLogger.d(TAG, "onResult:handleID:" + handleID + ":" + outputData[i].key)
|
|
||||||
val key = outputData[i].key //引擎结果的key
|
|
||||||
val bytes = outputData[i].value //识别结果
|
|
||||||
val result = String(bytes)
|
|
||||||
CallerLogger.d(TAG, "key=$key")
|
|
||||||
CallerLogger.d(TAG, "value=$result")
|
|
||||||
CallerLogger.d(TAG, "status=" + outputData[i].status)
|
|
||||||
if ((key == "func_wake_up" || key == "func_pre_wakeup")) {
|
|
||||||
CallerLogger.d(TAG,"$key: \n $result")
|
|
||||||
}
|
|
||||||
_wakeUpListener?.wakeupSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onEvent(i: Int, i1: Int, list: List<AiResponse>, o: Any) {
|
|
||||||
CallerLogger.i(TAG, "onEvent:$i,event:$i1")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(i: Int, i1: Int, s: String, o: Any) {
|
|
||||||
CallerLogger.d(TAG,"错误通知,能力执行终止,Ability $i ERROR::$s,err code:$i1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun writeRecording(aiStatus:AiStatus){
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 写入数据-录音方式
|
|
||||||
*/
|
|
||||||
val data = ByteArray(BUFFER_SIZE)
|
|
||||||
val read = audioRecord!!.read(data, 0, BUFFER_SIZE)
|
|
||||||
|
|
||||||
//平方和除以数据总长度,得到音量大小。
|
|
||||||
val volume = calculateVolume(data)
|
|
||||||
// CallerLogger.d(TAG,"当前分贝:${ abs(volume.toDouble())}")
|
|
||||||
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
|
|
||||||
//处理录音数据
|
|
||||||
write(data, aiStatus) //送尾帧
|
|
||||||
}
|
|
||||||
if (AiStatus.END == aiStatus) {
|
|
||||||
if ( audioRecord != null) {
|
|
||||||
audioRecord!!.stop()
|
|
||||||
isRecording.set(false)
|
|
||||||
end()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isRecording.get()) {
|
|
||||||
writeRecording(AiStatus.CONTINUE) //调用write方法送音频数据给引擎
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 结束会话
|
|
||||||
*/
|
|
||||||
private fun end() {
|
|
||||||
if (!isEnd.get()) {
|
|
||||||
val ret = AiHelper.getInst().end(aiHandle)
|
|
||||||
if (ret == 0) {
|
|
||||||
isEnd.set(true)
|
|
||||||
aiHandle = null
|
|
||||||
CallerLogger.d(TAG,"唤醒完成,end: $ret")
|
|
||||||
} else {
|
|
||||||
isEnd.set(false)
|
|
||||||
ThreadUtils.runOnUiThreadDelayed({
|
|
||||||
end()
|
|
||||||
CallerLogger.d(TAG,"关闭失败2s后重新广播唤醒完成,end: $ret")
|
|
||||||
},2_000)
|
|
||||||
CallerLogger.d(TAG,"唤醒完成,end: $ret")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 写入数据
|
|
||||||
*/
|
|
||||||
private fun write(part: ByteArray, status: AiStatus) {
|
|
||||||
if (isEnd.get()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val dataBuilder = AiRequest.builder()
|
|
||||||
var ret = 0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 送入音频需要标识音频的状态,第一帧为起始帧,status要传AiStatus.BEGIN,最后一帧为结束帧,status要传AiStatus.END,其他为中间帧,status要传AiStatus.CONTINUE
|
|
||||||
* 音频要求16bit,16K,单声道的pcm音频。
|
|
||||||
* 建议每次发送音频间隔40ms,每次发送音频字节数为一帧音频大小的整数倍。
|
|
||||||
*/
|
|
||||||
val aiAudio = AiAudio.get("wav").data(part).status(status).valid()
|
|
||||||
dataBuilder.payload(aiAudio)
|
|
||||||
|
|
||||||
ret = AiHelper.getInst().write(dataBuilder.build(), aiHandle)
|
|
||||||
if (ret != 0) {
|
|
||||||
CallerLogger.d(TAG,"write失败:$ret ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据录音数据计算音量
|
|
||||||
*/
|
|
||||||
private fun calculateVolume(buffer: ByteArray): Int {
|
|
||||||
var sumVolume = 0.0
|
|
||||||
var avgVolume = 0.0
|
|
||||||
var volume = 0
|
|
||||||
var i = 0
|
|
||||||
while (i < buffer.size) {
|
|
||||||
val v1 = buffer[i].toInt() and 0xFF
|
|
||||||
val v2 = buffer[i + 1].toInt() and 0xFF
|
|
||||||
var temp = v1 + (v2 shl 8) // 小端
|
|
||||||
if (temp >= 0x8000) {
|
|
||||||
temp = 0xffff - temp
|
|
||||||
}
|
|
||||||
sumVolume += abs(temp.toDouble())
|
|
||||||
i += 2
|
|
||||||
}
|
|
||||||
avgVolume = sumVolume / buffer.size / 2
|
|
||||||
volume = (log10(1 + avgVolume) * 10).toInt()
|
|
||||||
return volume
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建录音器
|
|
||||||
*/
|
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
private fun createAudioRecord() {
|
|
||||||
if (isRecording.get()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (audioRecord == null) {
|
|
||||||
Log.d(TAG, "createAudioRecord")
|
|
||||||
audioRecord = AudioRecord(
|
|
||||||
MediaRecorder.AudioSource.MIC,
|
|
||||||
16000,
|
|
||||||
AudioFormat.CHANNEL_IN_MONO,
|
|
||||||
AudioFormat.ENCODING_PCM_16BIT,
|
|
||||||
BUFFER_SIZE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始会话
|
|
||||||
*/
|
|
||||||
private fun start(): Int {
|
|
||||||
if (!keyword2File()) {
|
|
||||||
CallerLogger.d(TAG,"唤醒词文件写入失败,请检查是否有读写权限。")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
val customBuilder = AiRequest.builder()
|
|
||||||
customBuilder.customText("key_word", getIvwDir() + "/keyword.txt", 0)
|
|
||||||
var ret = AiHelper.getInst().loadData(ABILITYID, customBuilder.build())
|
|
||||||
if (ret != 0) {
|
|
||||||
CallerLogger.d(TAG,"open ivw loadData 失败:$ret")
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
CallerLogger.d(TAG,"open ivw loadData success:$ret")
|
|
||||||
val indexs = intArrayOf(0)
|
|
||||||
ret = AiHelper.getInst().specifyDataSet(ABILITYID, "key_word", indexs) //从缓存中把个性化资源设置到引擎中
|
|
||||||
if (ret != 0) {
|
|
||||||
CallerLogger.d(TAG,"open ivw specifyDataSet 失败:$ret")
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
CallerLogger.d(TAG,"open ivw specifyDataSet success:$ret")
|
|
||||||
|
|
||||||
val paramBuilder = AiRequest.builder()
|
|
||||||
paramBuilder.param("wdec_param_nCmThreshold", "0 0:800")
|
|
||||||
paramBuilder.param("gramLoad", true)
|
|
||||||
isEnd.set(false)
|
|
||||||
aiHandle = AiHelper.getInst().start(ABILITYID, paramBuilder.build(), null)
|
|
||||||
if (aiHandle?.code != 0) {
|
|
||||||
CallerLogger.d(TAG,"open ivw start失败:${aiHandle?.getCode()}")
|
|
||||||
return aiHandle?.code ?:0
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun keyword2File(): Boolean {
|
|
||||||
try {
|
|
||||||
val keywordFile: File = File(getIvwDir() + "/keyword.txt")
|
|
||||||
if (keywordFile.exists()) {
|
|
||||||
//强制清空内容
|
|
||||||
keywordFile.delete()
|
|
||||||
}
|
|
||||||
val binFile: File = File(getIvwDir() + "/keyword.bin")
|
|
||||||
if (binFile.exists()) {
|
|
||||||
binFile.delete()
|
|
||||||
}
|
|
||||||
var temp: String =weakupKey
|
|
||||||
if (temp.isEmpty()) {
|
|
||||||
temp = "你好小智"
|
|
||||||
}
|
|
||||||
val str = temp.replace(",", ",")
|
|
||||||
val keywords = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
|
||||||
if (!keywordFile.exists()) {
|
|
||||||
keywordFile.createNewFile()
|
|
||||||
}
|
|
||||||
val writer = OutputStreamWriter(
|
|
||||||
FileOutputStream(keywordFile),
|
|
||||||
"UTF-8"
|
|
||||||
)
|
|
||||||
val bufferedWriter = BufferedWriter(writer)
|
|
||||||
for (i in keywords.indices) {
|
|
||||||
bufferedWriter.write(keywords[i])
|
|
||||||
bufferedWriter.write(";")
|
|
||||||
bufferedWriter.newLine() //写入换行
|
|
||||||
}
|
|
||||||
bufferedWriter.close()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initWakeAi(context: Context) {
|
fun initWakeAi(context: Context) {
|
||||||
|
|
||||||
@@ -342,6 +50,7 @@ object WakeManager {
|
|||||||
file.mkdirs()
|
file.mkdirs()
|
||||||
}
|
}
|
||||||
AiHelper.getInst().setLogInfo(LogLvl.VERBOSE, 1, "${workDir}aeeLog.txt")
|
AiHelper.getInst().setLogInfo(LogLvl.VERBOSE, 1, "${workDir}aeeLog.txt")
|
||||||
|
AiHelper.getInst().setLogMode(2)
|
||||||
|
|
||||||
//设定初始化参数
|
//设定初始化参数
|
||||||
val params = BaseLibrary.Params.builder()
|
val params = BaseLibrary.Params.builder()
|
||||||
@@ -377,7 +86,7 @@ object WakeManager {
|
|||||||
val assets = Utils.getApp().assets.list(dir)?.toMutableList()
|
val assets = Utils.getApp().assets.list(dir)?.toMutableList()
|
||||||
val tartgetFile = File(targetDir)
|
val tartgetFile = File(targetDir)
|
||||||
if(tartgetFile.isDirectory){
|
if(tartgetFile.isDirectory){
|
||||||
tartgetFile.listFiles { dir, name ->
|
tartgetFile.listFiles { _, name ->
|
||||||
(assets?.contains(name)?:true).apply {
|
(assets?.contains(name)?:true).apply {
|
||||||
assets?.remove(name)
|
assets?.remove(name)
|
||||||
}
|
}
|
||||||
@@ -393,8 +102,4 @@ object WakeManager {
|
|||||||
}
|
}
|
||||||
throw IllegalArgumentException("找不到 Application")
|
throw IllegalArgumentException("找不到 Application")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIvwDir(): String {
|
|
||||||
return getWorkDir()+File.separator+"ivw"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,369 @@
|
|||||||
|
package com.mogo.mgintelligent.speech.iflytek
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.media.AudioFormat
|
||||||
|
import android.media.AudioRecord
|
||||||
|
import android.media.MediaRecorder
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.Message
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import com.iflytek.aikit.core.AiAudio
|
||||||
|
import com.iflytek.aikit.core.AiHandle
|
||||||
|
import com.iflytek.aikit.core.AiHelper
|
||||||
|
import com.iflytek.aikit.core.AiListener
|
||||||
|
import com.iflytek.aikit.core.AiRequest
|
||||||
|
import com.iflytek.aikit.core.AiResponse
|
||||||
|
import com.iflytek.aikit.core.AiStatus
|
||||||
|
import com.mogo.commons.AbsMogoApplication
|
||||||
|
import com.mogo.eagle.core.function.call.setting.CallerRequestActivityHandleManager
|
||||||
|
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||||
|
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||||
|
import java.io.BufferedWriter
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStreamWriter
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.log10
|
||||||
|
|
||||||
|
object WakeUpManager {
|
||||||
|
|
||||||
|
private const val START: Int = 0x0001
|
||||||
|
private const val WRITE_BY_RECORDING: Int = 0x0002
|
||||||
|
private const val END: Int = 0x0004
|
||||||
|
|
||||||
|
//录音缓冲区大小
|
||||||
|
private const val BUFFER_SIZE = 1280
|
||||||
|
|
||||||
|
private const val ABILITYID: String = "e867a88f2"
|
||||||
|
|
||||||
|
private const val weakupKey = "你好小智,小智小智,小智你好"
|
||||||
|
|
||||||
|
private val isEnd = AtomicBoolean(true)
|
||||||
|
|
||||||
|
//录音是否在进行
|
||||||
|
private val isRecording = AtomicBoolean(false)
|
||||||
|
|
||||||
|
private var aiHandle: AiHandle? = null
|
||||||
|
|
||||||
|
private const val TAG = "WakeUpManager"
|
||||||
|
|
||||||
|
private var mHandler: Handler? = null
|
||||||
|
|
||||||
|
private var audioRecord: AudioRecord? = null
|
||||||
|
|
||||||
|
private val mThread = Thread {
|
||||||
|
Looper.prepare()
|
||||||
|
mHandler = object : Handler(Looper.myLooper()!!) {
|
||||||
|
override fun handleMessage(msg: Message) {
|
||||||
|
super.handleMessage(msg)
|
||||||
|
when (msg.what) {
|
||||||
|
START -> {
|
||||||
|
/**
|
||||||
|
* 开始会话
|
||||||
|
*/
|
||||||
|
Log.d(TAG, "START")
|
||||||
|
val ret: Int = start()
|
||||||
|
if (ret == 0) {
|
||||||
|
val type = msg.arg1
|
||||||
|
if (type == WRITE_BY_RECORDING) {
|
||||||
|
createAudioRecord() //创建录音器
|
||||||
|
isRecording.set(true)
|
||||||
|
audioRecord?.startRecording() //录音器启动录音
|
||||||
|
}
|
||||||
|
mHandler?.removeCallbacksAndMessages(null) //清空消息队列
|
||||||
|
val writeMsg = Message()
|
||||||
|
writeMsg.what = type
|
||||||
|
writeMsg.obj = AiStatus.BEGIN
|
||||||
|
mHandler?.sendMessage(writeMsg) //调用write方法送音频数据给引擎
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_BY_RECORDING -> {
|
||||||
|
/**
|
||||||
|
* 写入数据-录音方式
|
||||||
|
*/
|
||||||
|
val status = msg.obj as AiStatus
|
||||||
|
val data = ByteArray(BUFFER_SIZE)
|
||||||
|
val read: Int = audioRecord?.read(data, 0, BUFFER_SIZE)?:AudioRecord.ERROR_INVALID_OPERATION
|
||||||
|
//平方和除以数据总长度,得到音量大小。
|
||||||
|
val volume: Int = calculateVolume(data)
|
||||||
|
//CallerLogger.d(TAG,"当前分贝:${ abs(volume.toDouble())}")
|
||||||
|
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
|
||||||
|
//处理录音数据
|
||||||
|
write(data, status) //送尾帧
|
||||||
|
}
|
||||||
|
if (AiStatus.END == status) {
|
||||||
|
if (audioRecord != null) {
|
||||||
|
audioRecord?.stop()
|
||||||
|
isRecording.set(false)
|
||||||
|
mHandler?.sendEmptyMessage(END)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isRecording.get()) {
|
||||||
|
val writeMsg = Message()
|
||||||
|
writeMsg.what = WRITE_BY_RECORDING
|
||||||
|
writeMsg.obj = AiStatus.CONTINUE
|
||||||
|
mHandler?.sendMessage(writeMsg) //调用write方法送音频数据给引擎
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END -> {
|
||||||
|
/**
|
||||||
|
* 结束会话
|
||||||
|
*/
|
||||||
|
Log.d(TAG, "END")
|
||||||
|
end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Looper.loop()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 能力监听回调
|
||||||
|
*/
|
||||||
|
private val edListener: AiListener = object : AiListener {
|
||||||
|
override fun onResult(handleID: Int, outputData: List<AiResponse>, usrContext: Any?) {
|
||||||
|
if (outputData.isNotEmpty()) {
|
||||||
|
for (i in outputData.indices) {
|
||||||
|
CallerLogger.d(TAG, "onResult:handleID:" + handleID + ":" + outputData[i].key)
|
||||||
|
val key = outputData[i].key //引擎结果的key
|
||||||
|
val bytes = outputData[i].value //识别结果
|
||||||
|
val result = String(bytes)
|
||||||
|
CallerLogger.d(TAG, "key=$key")
|
||||||
|
CallerLogger.d(TAG, "value=$result")
|
||||||
|
CallerLogger.d(TAG, "status=" + outputData[i].status)
|
||||||
|
if ((key == "func_wake_up" || key == "func_pre_wakeup")) {
|
||||||
|
CallerLogger.d(TAG,"$key: \n $result")
|
||||||
|
}
|
||||||
|
_wakeUpListener?.wakeupSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEvent(i: Int, i1: Int, list: List<AiResponse>, o: Any) {
|
||||||
|
CallerLogger.i(TAG, "onEvent:$i,event:$i1")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(i: Int, i1: Int, s: String, o: Any) {
|
||||||
|
CallerLogger.d(TAG,"错误通知,能力执行终止,Ability $i ERROR::$s,err code:$i1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _wakeUpListener:WakeUpListener?=null
|
||||||
|
|
||||||
|
fun setWakeUpListener(wakeUpListener:WakeUpListener?){
|
||||||
|
this._wakeUpListener = wakeUpListener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startThread(){
|
||||||
|
CallerLogger.d(TAG,"startThread")
|
||||||
|
mThread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startWakeUp() {
|
||||||
|
if (isRecording.get() || !isEnd.get()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
CallerLogger.d(TAG,"startWakeUp")
|
||||||
|
ThreadUtils.getIoPool().submit {
|
||||||
|
|
||||||
|
// 检测权限
|
||||||
|
val granted = ActivityCompat.checkSelfPermission(
|
||||||
|
AbsMogoApplication.getApp(),
|
||||||
|
Manifest.permission.RECORD_AUDIO)
|
||||||
|
if(granted != PackageManager. PERMISSION_GRANTED){
|
||||||
|
CallerRequestActivityHandleManager.requestPermission(TAG, Manifest.permission.RECORD_AUDIO)
|
||||||
|
return@submit
|
||||||
|
}
|
||||||
|
AiHelper.getInst().registerListener(ABILITYID, edListener)
|
||||||
|
val msg = Message()
|
||||||
|
msg.what = START
|
||||||
|
msg.arg1 = WRITE_BY_RECORDING
|
||||||
|
mHandler!!.sendMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopWakeup(){
|
||||||
|
CallerLogger.d(TAG,"stopWakeup")
|
||||||
|
if(!isEnd.get()) {
|
||||||
|
val msg = Message()
|
||||||
|
msg.what = WRITE_BY_RECORDING
|
||||||
|
msg.obj = AiStatus.END
|
||||||
|
mHandler!!.sendMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入数据
|
||||||
|
*/
|
||||||
|
private fun write(part: ByteArray, status: AiStatus) {
|
||||||
|
if (isEnd.get()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val dataBuilder = AiRequest.builder()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送入音频需要标识音频的状态,第一帧为起始帧,status要传AiStatus.BEGIN,最后一帧为结束帧,status要传AiStatus.END,其他为中间帧,status要传AiStatus.CONTINUE
|
||||||
|
* 音频要求16bit,16K,单声道的pcm音频。
|
||||||
|
* 建议每次发送音频间隔40ms,每次发送音频字节数为一帧音频大小的整数倍。
|
||||||
|
*/
|
||||||
|
val aiAudio = AiAudio.get("wav").data(part).status(status).valid()
|
||||||
|
dataBuilder.payload(aiAudio)
|
||||||
|
|
||||||
|
val ret: Int = AiHelper.getInst().write(dataBuilder.build(), aiHandle)
|
||||||
|
if (ret != 0) {
|
||||||
|
CallerLogger.d(TAG,"write失败:$ret ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建录音器
|
||||||
|
*/
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
private fun createAudioRecord() {
|
||||||
|
if (isRecording.get()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (audioRecord == null) {
|
||||||
|
Log.d(TAG, "createAudioRecord")
|
||||||
|
audioRecord = AudioRecord(
|
||||||
|
MediaRecorder.AudioSource.MIC,
|
||||||
|
16000,
|
||||||
|
AudioFormat.CHANNEL_IN_MONO,
|
||||||
|
AudioFormat.ENCODING_PCM_16BIT,
|
||||||
|
BUFFER_SIZE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据录音数据计算音量
|
||||||
|
*/
|
||||||
|
private fun calculateVolume(buffer: ByteArray): Int {
|
||||||
|
var sumVolume = 0.0
|
||||||
|
val volume: Int
|
||||||
|
var i = 0
|
||||||
|
while (i < buffer.size) {
|
||||||
|
val v1 = buffer[i].toInt() and 0xFF
|
||||||
|
val v2 = buffer[i + 1].toInt() and 0xFF
|
||||||
|
var temp = v1 + (v2 shl 8) // 小端
|
||||||
|
if (temp >= 0x8000) {
|
||||||
|
temp = 0xffff - temp
|
||||||
|
}
|
||||||
|
sumVolume += abs(temp.toDouble())
|
||||||
|
i += 2
|
||||||
|
}
|
||||||
|
val avgVolume: Double = sumVolume / buffer.size / 2
|
||||||
|
volume = (log10(1 + avgVolume) * 10).toInt()
|
||||||
|
return volume
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始会话
|
||||||
|
*/
|
||||||
|
private fun start(): Int {
|
||||||
|
if (!keyword2File()) {
|
||||||
|
CallerLogger.d(TAG,"唤醒词文件写入失败,请检查是否有读写权限。")
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
val customBuilder = AiRequest.builder()
|
||||||
|
customBuilder.customText("key_word", getIvwDir() + "/keyword.txt", 0)
|
||||||
|
var ret = AiHelper.getInst().loadData(ABILITYID, customBuilder.build())
|
||||||
|
if (ret != 0) {
|
||||||
|
CallerLogger.d(TAG,"open ivw loadData 失败:$ret")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
CallerLogger.d(TAG,"open ivw loadData success:$ret")
|
||||||
|
val indexs = intArrayOf(0)
|
||||||
|
ret = AiHelper.getInst().specifyDataSet(ABILITYID, "key_word", indexs) //从缓存中把个性化资源设置到引擎中
|
||||||
|
if (ret != 0) {
|
||||||
|
CallerLogger.d(TAG,"open ivw specifyDataSet 失败:$ret")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
CallerLogger.d(TAG,"open ivw specifyDataSet success:$ret")
|
||||||
|
|
||||||
|
val paramBuilder = AiRequest.builder()
|
||||||
|
paramBuilder.param("wdec_param_nCmThreshold", "0 0:800")
|
||||||
|
paramBuilder.param("gramLoad", true)
|
||||||
|
isEnd.set(false)
|
||||||
|
aiHandle = AiHelper.getInst().start(ABILITYID, paramBuilder.build(), null)
|
||||||
|
if (aiHandle?.code != 0) {
|
||||||
|
CallerLogger.d(TAG,"open ivw start失败:${aiHandle?.getCode()}")
|
||||||
|
return aiHandle?.code ?:0
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束会话
|
||||||
|
*/
|
||||||
|
private fun end() {
|
||||||
|
if (!isEnd.get()) {
|
||||||
|
val ret = AiHelper.getInst().end(aiHandle)
|
||||||
|
if (ret == 0) {
|
||||||
|
isEnd.set(true)
|
||||||
|
aiHandle = null
|
||||||
|
CallerLogger.d(TAG,"唤醒完成,end: $ret")
|
||||||
|
} else {
|
||||||
|
isEnd.set(false)
|
||||||
|
ThreadUtils.runOnUiThreadDelayed({
|
||||||
|
end()
|
||||||
|
CallerLogger.d(TAG,"关闭失败2s后重新广播唤醒完成,end: $ret")
|
||||||
|
},2_000)
|
||||||
|
CallerLogger.d(TAG,"唤醒完成,end: $ret")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun keyword2File(): Boolean {
|
||||||
|
try {
|
||||||
|
val keywordFile = File(getIvwDir() + "/keyword.txt")
|
||||||
|
if (keywordFile.exists()) {
|
||||||
|
//强制清空内容
|
||||||
|
keywordFile.delete()
|
||||||
|
}
|
||||||
|
val binFile = File(getIvwDir() + "/keyword.bin")
|
||||||
|
if (binFile.exists()) {
|
||||||
|
binFile.delete()
|
||||||
|
}
|
||||||
|
var temp: String = weakupKey
|
||||||
|
if (temp.isEmpty()) {
|
||||||
|
temp = "你好小智"
|
||||||
|
}
|
||||||
|
val str = temp.replace(",", ",")
|
||||||
|
val keywords = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
if (!keywordFile.exists()) {
|
||||||
|
keywordFile.createNewFile()
|
||||||
|
}
|
||||||
|
val writer = OutputStreamWriter(
|
||||||
|
FileOutputStream(keywordFile),
|
||||||
|
"UTF-8"
|
||||||
|
)
|
||||||
|
val bufferedWriter = BufferedWriter(writer)
|
||||||
|
for (i in keywords.indices) {
|
||||||
|
bufferedWriter.write(keywords[i])
|
||||||
|
bufferedWriter.write(";")
|
||||||
|
bufferedWriter.newLine() //写入换行
|
||||||
|
}
|
||||||
|
bufferedWriter.close()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIvwDir(): String {
|
||||||
|
return WakeManager.getWorkDir() +File.separator+"ivw"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user