feat(glass): 更新语音识别功能并优化欢迎界面

- 切换回线上服务器地址 "https://22v1322u01.vicp.fun"
- 添加"下一个"语音命令支持到离线命令服务
- 新增欢迎页面语音命令组(决策中心、紧急任务、当前任务)
- 在欢迎页面实现点动画效果显示识别状态
- 重构欢迎页面逻辑,移除演示按钮并简化UI布局
- 添加屏幕常亮标志以防止休眠影响语音识别
- 修复应用间跳转时的动画状态管理问题
这个提交包含在:
徐勤民 2026-04-16 19:17:50 +08:00
父节点 8582316cb8
当前提交 8c8e23c64c
共有 7 个文件被更改,包括 70 次插入128 次删除

查看文件

@ -14,8 +14,8 @@ import com.xuqm.base.di.manager.HttpManager;
*/ */
public class MyApplication extends App { public class MyApplication extends App {
public static String baseUrl = "http://192.168.6.20"; // public static String baseUrl = "http://192.168.6.20";
// public static String baseUrl = "http://22fs132201.imwork.net"; public static String baseUrl = "http://22fs132201.imwork.net";
@Override @Override
public void onCreate() { public void onCreate() {

查看文件

@ -31,8 +31,8 @@ object IntentRecognizeHelper {
private var questionIndex = 0 private var questionIndex = 0
private var disposable: Disposable? = null private var disposable: Disposable? = null
// private val baseUrl: String = "https://22v1322u01.vicp.fun" private val baseUrl: String = "https://22v1322u01.vicp.fun"
private val baseUrl: String = "http://192.168.6.20:12119" // private val baseUrl: String = "http://192.168.6.20:12119"
/** /**
* @param context 用于显示 Toast * @param context 用于显示 Toast

查看文件

@ -16,6 +16,7 @@ object OfflineCmdServiceHelper {
// 所有页面通用关键词(常量,只分配一次) // 所有页面通用关键词(常量,只分配一次)
private val COMMON_CMDS = listOf( private val COMMON_CMDS = listOf(
OfflineCmdBean("继续", "ji xu"), OfflineCmdBean("继续", "ji xu"),
OfflineCmdBean("下一个", "xia yi ge"),
OfflineCmdBean("退出", "tui chu"), OfflineCmdBean("退出", "tui chu"),
OfflineCmdBean("返回", "fan hui") OfflineCmdBean("返回", "fan hui")
) )
@ -76,6 +77,11 @@ object OfflineCmdServiceHelper {
private val CMDS_INSPECTION_COMPLETE = listOf( private val CMDS_INSPECTION_COMPLETE = listOf(
OfflineCmdBean("完成任务", "wan cheng ren wu") OfflineCmdBean("完成任务", "wan cheng ren wu")
) )
private val CMDS_WELCOME = listOf(
OfflineCmdBean("决策中心", "jue ce zhong xin"),
OfflineCmdBean("紧急任务", "jin ji ren wu"),
OfflineCmdBean("当前任务", "dang qian ren wu")
)
private var service: IOfflineCmdService? = null private var service: IOfflineCmdService? = null
@ -176,4 +182,8 @@ object OfflineCmdServiceHelper {
fun removeListenerInspectionComplete() = removeBeans(CMDS_INSPECTION_COMPLETE) fun removeListenerInspectionComplete() = removeBeans(CMDS_INSPECTION_COMPLETE)
fun addListenerWelcome() = registerBeans(CMDS_WELCOME)
fun removeListenerWelcome() = removeBeans(CMDS_WELCOME)
} }

查看文件

@ -26,7 +26,7 @@ class ChatActivity : BaseListFormLayoutNormalActivity<ChatItem, ChatVM, Activity
runOnUiThread { runOnUiThread {
when (cmd) { when (cmd) {
"退出", "返回", "退回" -> finish() "退出", "返回", "退回" -> finish()
"继续" -> recognizeAndChat() "继续","下一个" -> recognizeAndChat()
} }
} }
} }

查看文件

@ -2,6 +2,8 @@ package com.nova.brain.glass.ui
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.nova.brain.glass.R import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivityWelcomeBinding import com.nova.brain.glass.databinding.ActivityWelcomeBinding
@ -10,7 +12,6 @@ import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.viewmodel.WelcomeVM import com.nova.brain.glass.viewmodel.WelcomeVM
import com.xuqm.base.ui.BaseActivity import com.xuqm.base.ui.BaseActivity
import kotlin.jvm.java
class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() { class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
@ -19,18 +20,44 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
private lateinit var vm: WelcomeVM private lateinit var vm: WelcomeVM
// 点动画
private val tvOriginalText = "您可以说Nova,我的任务有哪些?"
private val dotsHandler = Handler(Looper.getMainLooper())
private var dotCount = 0
private val dotsRunnable = object : Runnable {
override fun run() {
dotCount = (dotCount % 3) + 1
binding.tv.text = "正在识别中${"·".repeat(dotCount)}"
dotsHandler.postDelayed(this, 500)
}
}
private fun startDotsAnim() {
dotCount = 0
dotsHandler.removeCallbacks(dotsRunnable)
dotsHandler.post(dotsRunnable)
}
private fun stopDotsAnim() {
dotsHandler.removeCallbacks(dotsRunnable)
binding.tv.text = tvOriginalText
}
override fun initView(savedInstanceState: Bundle?) { override fun initView(savedInstanceState: Bundle?) {
super.initView(savedInstanceState) super.initView(savedInstanceState)
vm = ViewModelProvider(this).get(WelcomeVM::class.java) vm = ViewModelProvider(this)[WelcomeVM::class.java]
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding.tv.setOnClickListener { binding.tv.setOnClickListener {
startActivity(Intent(this@WelcomeActivity, TaskListActivity::class.java)) startActivity(Intent(this@WelcomeActivity, TaskListActivity::class.java))
} }
binding.btnGet.setOnClickListener { vm.demoGet() } }
binding.btnPost.setOnClickListener { vm.demoPost() }
binding.md.setOnClickListener { override fun initData() {
binding.md.text = "请求中" super.initData()
binding.md.isClickable = false }
private fun triggerRecognize() {
startDotsAnim()
IntentRecognizeHelper.recognize( IntentRecognizeHelper.recognize(
context = this, context = this,
text = "当前阶段,最紧急的任务是什么?", text = "当前阶段,最紧急的任务是什么?",
@ -43,19 +70,10 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
} }
}, },
onComplete = { onComplete = {
binding.md.text = "决策中心" stopDotsAnim()
binding.md.isClickable = true
} }
) )
} }
}
override fun initData() {
super.initData()
vm.result.observe(this) { text ->
binding.tvResult.text = text
}
}
private val offlineCmdListener = object : OfflineCmdListener { private val offlineCmdListener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) { override fun onOfflineCmd(cmd: String) {
@ -64,6 +82,9 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
"任务列表", "查看任务", "查看任务列表" -> { "任务列表", "查看任务", "查看任务列表" -> {
startActivity(Intent(this@WelcomeActivity, TaskListActivity::class.java)) startActivity(Intent(this@WelcomeActivity, TaskListActivity::class.java))
} }
"决策中心", "紧急任务", "当前任务" -> {
triggerRecognize()
}
} }
} }
} }
@ -72,13 +93,15 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener) OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
binding.md.text = "决策中心" OfflineCmdServiceHelper.addListenerWelcome()
binding.md.isClickable = true stopDotsAnim() // 从 ChatActivity 返回时恢复原文
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener) OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener)
OfflineCmdServiceHelper.removeListenerWelcome()
dotsHandler.removeCallbacks(dotsRunnable)
} }
override fun onDestroy() { override fun onDestroy() {

查看文件

@ -14,102 +14,10 @@
android:text="您可以说Nova,我的任务有哪些?" android:text="您可以说Nova,我的任务有哪些?"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="100dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/btnRow" /> app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/btnRow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginHorizontal="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/scrollResult"
app:layout_constraintTop_toBottomOf="@id/tv">
<TextView
android:id="@+id/btnGet"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:gravity="center"
android:background="#33FFFFFF"
android:textColor="#ff3FFF5F"
android:textSize="14sp"
android:text="GET演示" />
<TextView
android:id="@+id/btnPost"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:gravity="center"
android:background="#33FFFFFF"
android:textColor="#ff3FFF5F"
android:textSize="14sp"
android:text="POST演示" />
<TextView
android:id="@+id/btnSse"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:gravity="center"
android:background="#33FFFFFF"
android:textColor="#ff3FFF5F"
android:textSize="14sp"
android:text="SSE演示" />
</LinearLayout>
<LinearLayout
android:id="@+id/btnRow2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginHorizontal="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/btnRow">
<TextView
android:id="@+id/md"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:gravity="center"
android:background="#33FFFFFF"
android:textColor="#ff3FFF5F"
android:textSize="14sp"
android:text="决策中心" />
</LinearLayout>
<ScrollView
android:id="@+id/scrollResult"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/btnRow2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/tvResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:textColor="#ff3FFF5F"
android:textSize="11sp"
android:fontFamily="monospace"
android:text="" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout> </layout>

查看文件

@ -43,6 +43,7 @@ public abstract class BaseActivity<V extends ViewDataBinding> extends AppCompatA
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
AppManager.getInstance().pushActivity(this); AppManager.getInstance().pushActivity(this);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mContext = this; mContext = this;
editText.clear(); editText.clear();
views.clear(); views.clear();