[xiaozhi]
This commit is contained in:
yangyakun
2024-03-08 20:26:16 +08:00
parent 3e395dd003
commit 3a2124db4e
302 changed files with 670 additions and 480 deletions

View File

@@ -137,7 +137,7 @@
android:layout_height="@dimen/dp_30"/>
<com.mogo.och.common.module.wigets.ZhiView
<com.mogo.och.common.module.manager.xiaozhimanager.ZhiView
android:id="@+id/zv_msg_pop_bottom"
android:layout_width="@dimen/dp_240"
android:layout_height="@dimen/dp_240"

View File

@@ -59,7 +59,7 @@
app:layout_constraintEnd_toEndOf="@+id/mapBizView"
app:layout_constraintStart_toStartOf="parent" />
<com.mogo.och.common.module.wigets.ZhiView
<com.mogo.och.common.module.manager.xiaozhimanager.ZhiView
android:id="@+id/zv_msg_pop_bottom"
android:layout_width="@dimen/dp_240"
android:layout_height="@dimen/dp_240"

View File

@@ -40,6 +40,14 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
res.srcDirs = [
'src/main/res',
'src/main/res/xiaozhi',
]
}
}
}
dependencies {

View File

@@ -0,0 +1,214 @@
package com.mogo.och.common.module.manager.xiaozhimanager
import android.Manifest
import androidx.core.app.ActivityCompat
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.VoiceMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.main.MainPresenter
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.permissions.PermissionsDialogUtils
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.och.common.module.utils.PermissionUtil
import com.mogo.och.common.module.wigets.toast.ToastCharterUtils
import com.mogo.tts.base.zhi.AsrTextBean
import com.mogo.tts.base.zhi.AvatarManager
import com.mogo.tts.base.zhi.CallbackWidget
import com.mogo.tts.base.zhi.ZhiRecordWinUi
import java.util.concurrent.atomic.AtomicBoolean
object ZhiStateManager : ZhiRecordWinUi {
private const val TAG = "ZhiStateManager"
@Volatile
private var status = ZhiRecordWinUi.RecordStatus.STATUS_SILENCE
private val enableZhi = AtomicBoolean(true)
init {
AvatarManager.addDistanceListener(TAG,this)
}
/**
* 开始对话
*/
override fun start(reason: String?) {
CallerLogger.d(TAG,"-----start 开始对话 $reason")
}
/**
* 语音卡状态变化
*
* @param status
*/
override fun onStatusChange(status: ZhiRecordWinUi.RecordStatus?) {
CallerLogger.d(TAG,"-----onStatusChange $status")
this.status = status?:ZhiRecordWinUi.RecordStatus.STATUS_SILENCE
when (status) {
ZhiRecordWinUi.RecordStatus.STATUS_SILENCE -> {// 进入默认状态
CallerLogger.d(TAG,"正在静默状态")
ZhiViewmanager.showListeningAni(ZhiViewmanager.normalAni)
}
ZhiRecordWinUi.RecordStatus.STATUS_LISTENING -> {// 正在监听唤醒人说话
CallerLogger.d(TAG,"正在监听唤醒人说话")
ZhiViewmanager.showListeningAni(ZhiViewmanager.listenerAni)
}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTANDING -> {// 小智正在理解中
CallerLogger.d(TAG,"正在理解")
}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTAND_END -> {// 理解完毕
CallerLogger.d(TAG,"理解结束")
}
ZhiRecordWinUi.RecordStatus.STATUS_SPEAKING -> {// 小智正在说话
CallerLogger.d(TAG,"小智正在说话")
ZhiViewmanager.showListeningAni(ZhiViewmanager.normalAni)
}
else -> {
}
}
}
/**
* 关闭对话
* @param trigger 是否手动
*/
override fun close(trigger: Boolean) {
CallerLogger.d(TAG,"-----close $trigger")
onStatusChange(ZhiRecordWinUi.RecordStatus.STATUS_SILENCE)
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = true,
msg = null,
isLastMsg = true,
isResp = true
)
pushMsgBox(msg)
}
/**
* 语音输入音量变化
*
* @param volume
*/
override fun onVolumeChange(volume: Int) {
CallerLogger.d(TAG,"-----onVolumeChange $volume")
}
/**
* 显示用户输入的内容
*
* @param asrTextBean
*/
override fun showInputText(asrTextBean: AsrTextBean?) {
CallerLogger.d(TAG,"-----showInputText $asrTextBean")
asrTextBean.let {
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = false,
msg = it?.text,
isLastMsg = it?.isLast == true,
isResp = false
)
pushMsgBox(msg)
}
}
/**
* 显示控件 暂时没有需求
*
* @param callbackWidget
*/
override fun showOutPutWidget(callbackWidget: CallbackWidget?) {
// todo 咱不支持定制显示 包括天气
CallerLogger.d(TAG,"-----showOutPutWidget $callbackWidget")
}
/**
* 显示系统输出内容
*
* @param outPutText
*/
override fun showOutputText(outPutText: String?) {
CallerLogger.d(TAG,"-----showOutputText $outPutText")
outPutText?.let {
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = false,
msg = it,
isLastMsg = false,
isResp = true
)
pushMsgBox(msg)
}
}
fun setZhiEnable(enable:Boolean){
if(enable){// 可用
enableZhi.set(true)
AvatarManager.enableXiaoZhi(false)
}else{// 不可用
enableZhi.set(false)
AvatarManager.enableXiaoZhi(true)
}
}
fun weakUpXiaoZhi(){
if (!AppIdentityModeUtils.isTaxiPassenger(FunctionBuildConfig.appIdentityMode)) {
return
}
if (!isFastClick()) {
ToastCharterUtils.showToastShort("请稍后唤醒")
return
}
if (PermissionUtil.checkPermission(AbsMogoApplication.getApp(), Manifest.permission.RECORD_AUDIO)) {
if(enableZhi.get()) {
AvatarManager.wakeupXiaoZhi()
}
}else{
//申请悬浮窗权限
val shouldShowRequestPermissionRationale = ActivityUtils.getTopActivity()
.shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)
if(shouldShowRequestPermissionRationale){// 可以弹窗系统权限框
ActivityCompat.requestPermissions(
ActivityUtils.getTopActivity(),
arrayOf(
Manifest.permission.RECORD_AUDIO,
), MainPresenter.MOGO_PERMISSION_REQUEST_CODE
)
}else{// 不会弹系统弹窗
PermissionsDialogUtils.openAppDetails(ActivityUtils.getTopActivity(), "录音机", 100)
}
}
}
// 两次点击按钮之间的点击间隔不能少于1000毫秒
private const val MIN_CLICK_DELAY_TIME = 3000
private var lastClickTime: Long = 0
private fun isFastClick(): Boolean {
var flag = false
val curClickTime = System.currentTimeMillis()
if (curClickTime - lastClickTime >= MIN_CLICK_DELAY_TIME) {
flag = true
}
lastClickTime = curClickTime
return flag
}
private fun pushMsgBox(msg: VoiceMsg){
CallerMsgBoxManager.saveMsgBox(MsgBoxBean(MsgBoxType.VOICE, msg))
}
}

View File

@@ -0,0 +1,73 @@
package com.mogo.och.common.module.manager.xiaozhimanager
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.utils.FrameAnimatorContainer
import com.mogo.tts.base.zhi.CallbackWidget
import com.mogo.tts.base.zhi.ZhiRecordWinUi
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.atomic.AtomicBoolean
class ZhiView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr), ZhiViewmanager.IViewCallback {
companion object {
const val TAG = "ZhiView"
}
// 播放默认小智
// 传递播放一次的动画
// 传递开始播放
private var currentAnim:FrameAnimatorContainer? = null
init {
setOnClickListener {
ZhiStateManager.weakUpXiaoZhi()
}
}
override fun setFirstPlayAni(initAni: ZhiViewmanager.AniData,aniListener:FrameAnimatorContainer.OnAnimationStoppedListener){
currentAnim = FrameAnimatorContainer(initAni.aniArrayId, 12,this)
currentAnim?.isOnce = initAni.isOnce
currentAnim?.sequence = initAni.sequence
currentAnim?.setFtp(initAni.fps)
currentAnim?.setOnAnimStopListener(aniListener)
currentAnim?.reStart()
}
override fun setNewPlayData(currentPalyingAni: ZhiViewmanager.AniData) {
currentAnim?.setData(currentPalyingAni.aniList)
currentAnim?.isOnce = currentPalyingAni.isOnce
currentAnim?.sequence = currentPalyingAni.sequence
currentAnim?.setFtp(currentPalyingAni.fps)
}
override fun changeAniImmediately(currentPalyingAni: ZhiViewmanager.AniData) {
currentAnim?.setData(currentPalyingAni.aniList)
currentAnim?.isOnce = currentPalyingAni.isOnce
currentAnim?.sequence = currentPalyingAni.sequence
currentAnim?.setFtp(currentPalyingAni.fps)
currentAnim?.reStart()
}
override fun restartAni() {
currentAnim?.reStart()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
ZhiViewmanager.addDistanceListener(this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
ZhiViewmanager.removeListener()
}
}

View File

@@ -0,0 +1,137 @@
package com.mogo.och.common.module.manager.xiaozhimanager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.R
import com.mogo.och.common.module.utils.FrameAnimatorContainer
import java.util.concurrent.ArrayBlockingQueue
object ZhiViewmanager {
private const val TAG = "ZhiViewmanager"
private var iViewCallbacks: IViewCallback? = null
val normalAni = AniData(1, R.array.xiaozhi_normal, false, true,true,12)
val listenerAni = AniData(2,R.array.xiaozhi_think,false,true,true,12)
val listener2Normal = AniData(3, R.array.xiaozhi_think_normal, true, false,true,24)
val normal2Listener = AniData(4, R.array.xiaozhi_think_normal, true, true,true,24)
val beltAni = AniData(5, R.array.xiaozhi_belt, false, true,true,12)
val loveAni = AniData(6, R.array.xiaozhi_love, false, true,true,12)
private var initAni = normalAni
private var currentAni: AniData? = null
private val readQueue = ArrayBlockingQueue<AniData>(8, true)
fun addDistanceListener(listener: IViewCallback) {
this.iViewCallbacks = listener
this.currentAni = initAni
listener.setFirstPlayAni(initAni,
object : FrameAnimatorContainer.OnAnimationStoppedListener {
override fun playOnce() {
CallerLogger.d(TAG, "播放完一遍动画")
var nextPlay = readQueue.poll()
CallerLogger.d(TAG, "获取下一个动画${Thread.currentThread().name}--${nextPlay?.id}-${readQueue.size}")
if(nextPlay == currentAni){
return
}
if(nextPlay==null){
if(currentAni?.isOnce==true) {
// 没有设置新的动画 且上一个动画是直播一次的动画
currentAni = initAni
iViewCallbacks?.setNewPlayData(initAni)
}else{
// 没有设置新的动画 且上一个动画时循环动画
return
}
}else{
// 有设置新的动画
currentAni = nextPlay
CallerLogger.d(TAG, "切换动画${nextPlay.id}")
iViewCallbacks?.setNewPlayData(nextPlay)
}
}
override fun AnimationStopped() {
CallerLogger.d(TAG, "动画停止")
listener.restartAni()
}
})
}
fun removeListener() {
iViewCallbacks = null
}
fun showListeningAni(aniData: AniData) {
var lastAni = readQueue.peek()
if(lastAni==null){
lastAni = currentAni
}
if(lastAni?.id==aniData.id){
return
}
when (lastAni?.id) {
1 -> {//正在播放默认动画
if(aniData.id==2){
iViewCallbacks?.changeAniImmediately(normal2Listener)
currentAni = normal2Listener
CallerLogger.d(TAG, "立刻播放${Thread.currentThread().name}--${normal2Listener.id}-${readQueue.size}")
readQueue.offer(aniData)
CallerLogger.d(TAG, "排队播放${Thread.currentThread().name}--${aniData.id}-${readQueue.size}")
}else{
iViewCallbacks?.changeAniImmediately(aniData)
currentAni = aniData
CallerLogger.d(TAG, "立刻播放${Thread.currentThread().name}--${aniData.id}-${readQueue.size}")
}
}
2 -> {// 正在播放倾听中动画
if(aniData.id==1){
iViewCallbacks?.changeAniImmediately(listener2Normal)
currentAni = listener2Normal
CallerLogger.d(TAG, "立刻播放${Thread.currentThread().name}--${listener2Normal.id}-${readQueue.size}")
readQueue.offer(aniData)
CallerLogger.d(TAG, "排队播放${Thread.currentThread().name}--${aniData.id}-${readQueue.size}")
}else{
iViewCallbacks?.changeAniImmediately(aniData)
currentAni = aniData
CallerLogger.d(TAG, "立刻播放${Thread.currentThread().name}--${aniData.id}-${readQueue.size}")
}
}
else -> {
iViewCallbacks?.changeAniImmediately(aniData)
currentAni = aniData
CallerLogger.d(TAG, "立刻播放${Thread.currentThread().name}--${aniData.id}-${readQueue.size}")
}
}
}
interface IViewCallback {
fun setFirstPlayAni(
currentPalyingAni: AniData,
aniListener: FrameAnimatorContainer.OnAnimationStoppedListener
)
fun setNewPlayData(currentPalyingAni: AniData)
fun changeAniImmediately(currentPalyingAni: AniData)
fun restartAni()
}
data class AniData(
val id: Int,// 动画ID
val aniArrayId: Int,// 动画序列号
val isOnce: Boolean,// true 只播一次 false 循环播放
val sequence: Boolean,// true 正向播放 false 倒着播放
val immediately:Boolean,
val fps:Int
) {
var aniList = FrameAnimatorContainer.getData(aniArrayId)
}
}

View File

@@ -33,6 +33,24 @@ class FrameAnimatorContainer (resId: Int,
var isOnce:Boolean = false
var sequence:Boolean = true
fun setFtp(fps:Int){
mDelayMillis = 1000 / fps
}
companion object{
fun getData(resId: Int): IntArray {
val array = AbsMogoApplication.getApp().resources.obtainTypedArray(resId)
val len = array.length()
val intArray = IntArray(array.length())
for (i in 0 until len) {
intArray[i] = array.getResourceId(i, 0)
}
array.recycle()
return intArray
}
}
init {
createAnimation(imageView, getData(resId), fps,initFirstFrame,width,height)
this.isOnce = isOnce
@@ -87,16 +105,24 @@ class FrameAnimatorContainer (resId: Int,
private val next: Int
get() {
mIndex++
var isPlayOnce = false
if (mIndex >= mFrames.size){
mIndex = 0
if(isOnce){// 一次性动画 播放完毕后直接结束
stop()
}
isPlayOnce = true
}
if(!sequence){// 倒叙
return mFrames[mFrames.size-1-mIndex]
val nextInfo= if(sequence){// 倒叙
mFrames[mIndex]
}else{
mFrames[mFrames.size-1-mIndex]
}
return mFrames[mIndex]
if(isPlayOnce){// 锁定nextInfo 在回调中可能会修改mFrames值
mOnAnimationStoppedListener?.playOnce()
}
return nextInfo
}
@Synchronized
@@ -120,9 +146,8 @@ class FrameAnimatorContainer (resId: Int,
val imageView = mSoftReferenceImageView!!.get()
if (!mShouldRun || imageView == null) {
mIsRunning = false
if (mOnAnimationStoppedListener != null) {
mOnAnimationStoppedListener!!.AnimationStopped()
}
mOnAnimationStoppedListener?.AnimationStopped()
Logger.d(TAG, "结束动画1")
return
}
mIsRunning = true
@@ -131,9 +156,8 @@ class FrameAnimatorContainer (resId: Int,
val imageRes: Int = next
if (!mShouldRun || imageView == null) {
mIsRunning = false
if (mOnAnimationStoppedListener != null) {
mOnAnimationStoppedListener!!.AnimationStopped()
}
mOnAnimationStoppedListener?.AnimationStopped()
Logger.d(TAG, "结束动画2")
return
}
mHandler?.postDelayed(this, mDelayMillis.toLong())
@@ -195,16 +219,6 @@ class FrameAnimatorContainer (resId: Int,
* @param resId
* @return
*/
fun getData(resId: Int): IntArray {
val array = AbsMogoApplication.getApp().resources.obtainTypedArray(resId)
val len = array.length()
val intArray = IntArray(array.length())
for (i in 0 until len) {
intArray[i] = array.getResourceId(i, 0)
}
array.recycle()
return intArray
}
fun setData(mFrames: IntArray){
this.mFrames = mFrames
@@ -215,5 +229,6 @@ class FrameAnimatorContainer (resId: Int,
*/
interface OnAnimationStoppedListener {
fun AnimationStopped()
fun playOnce(){}
}
}

View File

@@ -24,7 +24,13 @@ object VoiceNotice {
}
@JvmStatic
fun showNotice(notice: String?, level: Int, delayed: Long = 0) {
fun showNotice(notice: String?, delayed: Long,callback:IMogoTTSCallback ) {
showNotice(notice, AIAssist.LEVEL0, delayed,callback)
}
@JvmStatic
fun showNotice(notice: String?, level: Int, delayed: Long = 0,callback:IMogoTTSCallback?=null) {
notice?.let {
if (delayed == 0L) {
UiThreadHandler.post {

View File

@@ -1,281 +0,0 @@
package com.mogo.och.common.module.wigets
import android.Manifest
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.app.ActivityCompat
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.VoiceMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.main.MainPresenter
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.mogo.permissions.PermissionsDialogUtils
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.ClickUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.utils.FrameAnimatorContainer
import com.mogo.och.common.module.utils.PermissionUtil
import com.mogo.och.common.module.wigets.toast.ToastCharterUtils
import com.mogo.tts.base.zhi.AsrTextBean
import com.mogo.tts.base.zhi.AvatarManager
import com.mogo.tts.base.zhi.CallbackWidget
import com.mogo.tts.base.zhi.ZhiRecordWinUi
import java.util.concurrent.atomic.AtomicBoolean
class ZhiView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr),
ZhiRecordWinUi {
companion object {
const val TAG = "ZhiView"
}
private var currentAnim = FrameAnimatorContainer(R.array.xiaozhi_normal, 12,this)
@Volatile
private var status = ZhiRecordWinUi.RecordStatus.STATUS_SILENCE
private var animalState = AnimalState.Normal
private val enableZhi = AtomicBoolean(true)
init {
val xiaozhiNormal = currentAnim.getData(R.array.xiaozhi_normal)
val xiaozhiThink = currentAnim.getData(R.array.xiaozhi_think)
val xiaozhiThinkNormal = currentAnim.getData(R.array.xiaozhi_think_normal)
currentAnim.setOnAnimStopListener(object : FrameAnimatorContainer.OnAnimationStoppedListener{
override fun AnimationStopped() {
when (status) {
ZhiRecordWinUi.RecordStatus.STATUS_SILENCE -> {
if(animalState==AnimalState.SPEAK){
currentAnim.setData(xiaozhiThinkNormal)
currentAnim.isOnce = true
currentAnim.sequence = false
currentAnim.reStart()
animalState = AnimalState.NORMAL_SPEAK
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status speak to normal")
}else{
currentAnim.setData(xiaozhiNormal)
currentAnim.isOnce = false
currentAnim.sequence = true
currentAnim.reStart()
animalState = AnimalState.Normal
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status normal")
}
}
ZhiRecordWinUi.RecordStatus.STATUS_LISTENING -> {
if(animalState==AnimalState.Normal){
currentAnim.setData(xiaozhiThinkNormal)
currentAnim.isOnce = true
currentAnim.sequence = true
currentAnim.reStart()
animalState = AnimalState.NORMAL_SPEAK
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status normal to speak")
}else{
currentAnim.setData(xiaozhiThink)
currentAnim.isOnce = false
currentAnim.sequence = true
currentAnim.reStart()
animalState = AnimalState.SPEAK
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status speak")
}
}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTANDING -> {}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTAND_END -> {}
ZhiRecordWinUi.RecordStatus.STATUS_SPEAKING -> {
if(animalState==AnimalState.SPEAK){
currentAnim.setData(xiaozhiThinkNormal)
currentAnim.isOnce = true
currentAnim.sequence = false
currentAnim.reStart()
animalState = AnimalState.NORMAL_SPEAK
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status speak to normal")
}else{
currentAnim.setData(xiaozhiNormal)
currentAnim.isOnce = false
currentAnim.sequence = true
currentAnim.reStart()
animalState = AnimalState.Normal
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "动画$status normal")
}
}
}
}
})
setOnClickListener {
if (!AppIdentityModeUtils.isTaxiPassenger(FunctionBuildConfig.appIdentityMode)) {
return@setOnClickListener
}
if (ClickUtils.isClickTooFrequent(this,3000)) {
ToastCharterUtils.showToastShort("请稍后唤醒")
return@setOnClickListener
}
if (PermissionUtil.checkPermission(context,Manifest.permission.RECORD_AUDIO)) {
if(enableZhi.get()) {
AvatarManager.wakeupXiaoZhi()
}
}else{
//申请悬浮窗权限
val shouldShowRequestPermissionRationale = ActivityUtils.getTopActivity()
.shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)
if(shouldShowRequestPermissionRationale){// 可以弹窗系统权限框
ActivityCompat.requestPermissions(ActivityUtils.getTopActivity(),
arrayOf(
Manifest.permission.RECORD_AUDIO,
), MainPresenter.MOGO_PERMISSION_REQUEST_CODE
)
}else{// 不会弹系统弹窗
PermissionsDialogUtils.openAppDetails(ActivityUtils.getTopActivity(), "录音机", 100)
}
}
}
}
fun setZhiEnable(enable:Boolean){
if(enable){// 可用
enableZhi.set(true)
AvatarManager.enableXiaoZhi(false)
}else{// 不可用
enableZhi.set(false)
AvatarManager.enableXiaoZhi(true)
}
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "焦点与否:${hasWindowFocus}")
AvatarManager.enableXiaoZhi(!hasWindowFocus)
if(hasWindowFocus){
currentAnim.reStart()
}else{
currentAnim.stop()
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
AvatarManager.addDistanceListener(TAG,this)
currentAnim.reStart()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
AvatarManager.removeListener(TAG)
}
override fun start(reason: String?) {
CallerLogger.d(TAG,"-----start $reason")
}
override fun onStatusChange(status: ZhiRecordWinUi.RecordStatus?) {
CallerLogger.d(TAG,"-----onStatusChange $status")
this.status = status?:ZhiRecordWinUi.RecordStatus.STATUS_SILENCE
when (status) {
ZhiRecordWinUi.RecordStatus.STATUS_SILENCE -> {
currentAnim.stop()
}
ZhiRecordWinUi.RecordStatus.STATUS_LISTENING -> {// 监听中
currentAnim.stop()
}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTANDING -> {
// 正在理解
CallerLogger.d(TAG,"正在理解")
}
ZhiRecordWinUi.RecordStatus.STATUS_UNDERSTAND_END -> {
CallerLogger.d(TAG,"理解结束")
}
ZhiRecordWinUi.RecordStatus.STATUS_SPEAKING -> {
// 正在说话
currentAnim.stop()
}
else -> {
}
}
}
override fun close(trigger: Boolean) {
CallerLogger.d(TAG,"-----close $trigger")
onStatusChange(ZhiRecordWinUi.RecordStatus.STATUS_SILENCE)
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = true,
msg = null,
isLastMsg = true,
isResp = true
)
pushMsgBox(msg)
}
override fun onVolumeChange(volume: Int) {
CallerLogger.d(TAG,"-----onVolumeChange $volume")
}
/**
* 用户输入的
*/
override fun showInputText(asrTextBean: AsrTextBean?) {
CallerLogger.d(TAG,"-----showInputText $asrTextBean")
asrTextBean.let {
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = false,
msg = it?.text,
isLastMsg = it?.isLast == true,
isResp = false
)
pushMsgBox(msg)
}
}
/**
* 特定View
*/
override fun showOutPutWidget(callbackWidget: CallbackWidget?) {
// todo 咱不支持定制显示 包括天气
CallerLogger.d(TAG,"-----showOutPutWidget $callbackWidget")
}
/**
* 小智说的
*/
override fun showOutputText(outPutText: String?) {
CallerLogger.d(TAG,"-----showOutputText $outPutText")
outPutText?.let {
val msg = VoiceMsg(
isWakeUp = false,
isWakeUpEnd = false,
msg = it,
isLastMsg = false,
isResp = true
)
pushMsgBox(msg)
}
}
private fun pushMsgBox(msg:VoiceMsg){
CallerMsgBoxManager.saveMsgBox(MsgBoxBean(MsgBoxType.VOICE, msg))
}
enum class AnimalState {
Normal,
NORMAL_SPEAK,
SPEAK_NORMAL,
SPEAK,
}
}

Some files were not shown because too many files have changed in this diff Show More