diff --git a/app/src/main/java/com/xiaoqu/watch/device/sensor/FiseVibrationController.kt b/app/src/main/java/com/xiaoqu/watch/device/sensor/FiseVibrationController.kt index 4d3a324..4edd0ea 100644 --- a/app/src/main/java/com/xiaoqu/watch/device/sensor/FiseVibrationController.kt +++ b/app/src/main/java/com/xiaoqu/watch/device/sensor/FiseVibrationController.kt @@ -24,7 +24,8 @@ import javax.inject.Singleton @Singleton class FiseVibrationController @Inject constructor( @ApplicationContext private val context: Context, - private val configManager: VibrationConfigManager + private val configManager: VibrationConfigManager, + private val edgeTtsManager: com.xiaoqu.watch.service.manager.EdgeTtsManager ) : VibrationController { /** 系统振动器 */ @@ -98,9 +99,11 @@ class FiseVibrationController @Inject constructor( } } - // 音频:系统级开关 + 用户级开关 + 有音频文件 - if (voiceOk) { + // 音频:系统级开关 + 用户级开关 + 有音频文件 + TTS 未在播放 + if (voiceOk && !edgeTtsManager.isPlaying) { playAudio(pattern.audioResId, configManager.voiceVolume) + } else if (voiceOk && edgeTtsManager.isPlaying) { + Timber.d("振动: TTS 播放中,跳过提示音") } } diff --git a/app/src/main/java/com/xiaoqu/watch/ui/task/TaskDetailFragment.kt b/app/src/main/java/com/xiaoqu/watch/ui/task/TaskDetailFragment.kt index 7075b60..5faf544 100644 --- a/app/src/main/java/com/xiaoqu/watch/ui/task/TaskDetailFragment.kt +++ b/app/src/main/java/com/xiaoqu/watch/ui/task/TaskDetailFragment.kt @@ -13,6 +13,7 @@ import com.xiaoqu.watch.databinding.FragmentTaskDetailBinding import com.xiaoqu.watch.network.ApiResult import com.xiaoqu.watch.network.api.TaskApi import com.xiaoqu.watch.network.safeApiCall +import com.xiaoqu.watch.service.manager.EdgeTtsManager import com.xiaoqu.watch.service.manager.NfcTaskManager import com.xiaoqu.watch.ui.common.BaseFragment import com.xiaoqu.watch.ui.widget.QuTipDialog @@ -30,6 +31,7 @@ class TaskDetailFragment : BaseFragment() { @Inject lateinit var taskApi: TaskApi @Inject lateinit var nfcTaskManager: NfcTaskManager + @Inject lateinit var edgeTtsManager: EdgeTtsManager /** 当前任务数据 */ private var taskDetail: TaskDetail? = null @@ -53,6 +55,9 @@ class TaskDetailFragment : BaseFragment() { findNavController().popBackStack() } + // TTS 播放按钮 + binding.btnTts.setOnClickListener { toggleTts() } + // 从导航参数获取任务 ID val taskId = arguments?.getLong("taskId", 0) ?: 0 if (taskId > 0) { @@ -284,4 +289,69 @@ class TaskDetailFragment : BaseFragment() { } } } + + // ===== TTS 语音播报 ===== + + /** 切换播放/停止 */ + private fun toggleTts() { + if (edgeTtsManager.isPlaying) { + stopTts() + } else { + startTts() + } + } + + /** 开始播报当前任务内容 */ + private fun startTts() { + val detail = taskDetail ?: return + + // 拼接播报文本:有值的字段才读,空字段跳过 + val parts = mutableListOf() + if (detail.name.isNotBlank()) parts.add("任务:${detail.displayName}") + if (detail.positionText.isNotBlank()) parts.add("地点:${detail.positionText}") + if (detail.sendTime.isNotBlank()) parts.add("时间:${detail.sendTime}") + if (detail.point > 0) parts.add("积分:${detail.pointText}") + if (detail.content.isNotBlank()) parts.add("备注:${detail.content}") + + if (parts.isEmpty()) return + + val text = parts.joinToString(",") + Timber.d("TTS 播报: $text") + + // 更新按钮状态为播放中 + updateTtsButton(playing = true) + + // 播放完成回调:恢复按钮 + edgeTtsManager.onComplete = { + activity?.runOnUiThread { updateTtsButton(playing = false) } + } + + edgeTtsManager.speak(text) { errorMsg -> + Timber.w("TTS 播报失败: $errorMsg") + updateTtsButton(playing = false) + } + } + + /** 停止播报 */ + private fun stopTts() { + edgeTtsManager.stop() + updateTtsButton(playing = false) + } + + /** 更新 TTS 按钮的 UI 状态 */ + private fun updateTtsButton(playing: Boolean) { + binding.btnTts.setImageResource( + if (playing) R.drawable.ic_speaker_stop else R.drawable.ic_speaker + ) + binding.btnTts.setBackgroundResource( + if (playing) R.drawable.bg_tts_button_active else R.drawable.bg_tts_button + ) + } + + override fun onDestroyView() { + // 离开页面自动停止播放 + edgeTtsManager.stop() + edgeTtsManager.onComplete = null + super.onDestroyView() + } } diff --git a/app/src/main/res/drawable/bg_tts_button.xml b/app/src/main/res/drawable/bg_tts_button.xml new file mode 100644 index 0000000..40625ab --- /dev/null +++ b/app/src/main/res/drawable/bg_tts_button.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_tts_button_active.xml b/app/src/main/res/drawable/bg_tts_button_active.xml new file mode 100644 index 0000000..b88c5ba --- /dev/null +++ b/app/src/main/res/drawable/bg_tts_button_active.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_speaker.xml b/app/src/main/res/drawable/ic_speaker.xml new file mode 100644 index 0000000..3db204b --- /dev/null +++ b/app/src/main/res/drawable/ic_speaker.xml @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_speaker_stop.xml b/app/src/main/res/drawable/ic_speaker_stop.xml new file mode 100644 index 0000000..4b4527a --- /dev/null +++ b/app/src/main/res/drawable/ic_speaker_stop.xml @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_task_detail.xml b/app/src/main/res/layout/fragment_task_detail.xml index 0801f49..9e2f4fa 100644 --- a/app/src/main/res/layout/fragment_task_detail.xml +++ b/app/src/main/res/layout/fragment_task_detail.xml @@ -101,6 +101,18 @@ + + +