修复每次开机屏保需要重新获取的bug
authorxue <2144439972@qq.com>
Fri, 6 Mar 2026 06:36:59 +0000 (14:36 +0800)
committerxue <2144439972@qq.com>
Fri, 6 Mar 2026 06:36:59 +0000 (14:36 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp

index afc36ee..10f3c5b 100644 (file)
@@ -305,6 +305,11 @@ namespace OHOS
         
         // 退出哄睡模式时恢复表情
         void OnExitLullabyMode();
+
+        /** 对话模式播放语音界面:启动 BGM 混播(仅从聆听进入说话时调用) */
+        void StartDialogueBgm();
+        /** 对话模式离开播放语音界面:停止 BGM */
+        void StopDialogueBgm();
         
         // 音频文本队列操作函数
         void EnqueueAudioText(const std::string& text);
index 763a5c1..845ccac 100644 (file)
@@ -1495,7 +1495,16 @@ extern "C" {
         json_buf[n] = '\0';
         ParseCharacterConfigData(json_buf);
         fclose(file);
-        printf("[DEVICE_CHARACTER] read character config success\n");
+         // hasScreenImage_ 非服务端字段,由角色配置变更时写入 KV,此处从 KV 恢复
+        // UtilsGetValue 成功时:从文件返回 value 长度(如 "1" 返回 1),从缓存返回 0;失败返回负数
+        char temp[16] = {0};
+        int kvRet = UtilsGetValue("character_has_screen_image", temp, sizeof(temp));
+        if (kvRet >= 0 && temp[0] == '1') {
+            hasScreenImage_ = 1;
+        } else {
+            hasScreenImage_ = 0;
+        }
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DEVICE_CHARACTER] read character config success (hasScreenImage_=%d from KV, kvRet=%d)", hasScreenImage_, kvRet);
     }
     
     // 解析JSON中的data数据
@@ -2714,6 +2723,7 @@ extern "C" {
             last_hairColor_ = hairColor_;
             last_eyesColor_ = eyesColor_;
             last_hairStyle_ = hairStyle_;
+            last_hasScreenImage_ = hasScreenImage_;
             last_screenImageAsEmoji_ = screenImageAsEmoji_;
             return;
         }
@@ -2776,7 +2786,11 @@ extern "C" {
         last_screenImageAsEmoji_ = screenImageAsEmoji;
         last_hasScreenImage_ = hasScreenImage;
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleCharacterConfigChange: 角色配置已更新");
-        
+        // hasScreenImage 非服务端字段,仅本地使用;写入 KV 以便重启后恢复
+        (void)UtilsSetValue("character_has_screen_image", hasScreenImage ? "1" : "0");
+        // printf("character_has_screen_image: %s\n", hasScreenImage ? "1" : "0");
+        // printf("hasScreenImage_: %d\n", hasScreenImage_);
+
         // 角色切换完成后,上报蓝牙连接状态
         ln_bt_report_earphone_connection_status(false);  // 不需要弹窗
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleCharacterConfigChange: 角色切换完成,已上报蓝牙连接状态");
@@ -3370,6 +3384,24 @@ extern "C" {
         m_alwaysOnRefreshActive = false;
         m_alwaysOnRefreshTime = 0;
     }
+
+    //测试BGM开始函数
+    void ThunderBirdModel::StartDialogueBgm()
+    {
+        static const char *kDialogueBgmPath = "/user/res/music/BGM.mp3";
+        int ret = ln_audio_simple_play_loop(kDialogueBgmPath, true);
+        if (ret != 0) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StartDialogueBgm: play_loop %s failed, ret=%d", kDialogueBgmPath, ret);
+        } else {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StartDialogueBgm: BGM mix started: %s", kDialogueBgmPath);
+     }
+    }
+    //测试BGM停止函数
+    void ThunderBirdModel::StopDialogueBgm()
+    {
+        ln_audio_simple_stop();
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopDialogueBgm: BGM stopped");
+    }
     
     void ThunderBirdModel::HandleBluetoothConnect(const char *bluetoothAddress)
     {
@@ -3455,6 +3487,20 @@ extern "C" {
                 if(ThunderBirdMainView::GetInstance()){
                     uapi_set_screen_on_api(); // 亮屏
                     int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); //获取当前视图
+                    int currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+                    // 如果是从对话模式(说话/聆听)跳转到绑定成功界面,则先退出对话模式再跳转
+                    if (currentView == THUNDERBIRD_DIALOGUEVIEW &&
+                        (currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING ||
+                         currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)) {
+                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleBindAndUnbind: 从对话模式跳转绑定成功,先退出对话模式");
+                        StopCountUpTimer();
+                        ThunderBirdPresenter::GetInstance()->SetDialogueing(false);
+                        ln_ws_end_audio_chat();//结束对话
+                        AI_ForceInterrupt();
+                        ln_ws_send_voice_chat_interrupt("退出对话");
+                        OnExitDialogueMode();
+                        do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_AUDIO_DEINIT, NULL, 0);
+                    }
                     ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_ADJUSTVIEW, ThunderBirdAdjustView::THUNDERBIRD_ADJUSTVIEW_BIND_SUCCESS);
                 }
                 int volume = AudioManager::GetInstance().SetVolume(AUDIO_STREAM_VOICE_ASSISTANT, 50);
@@ -3469,6 +3515,7 @@ extern "C" {
             {
                 //增加设备解绑提示
                 int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); //获取当前视图
+                int currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleBindAndUnbind: 设备已解绑,显示解绑警告");
                 uapi_set_screen_on_api();
                 bind_status = false;//解绑标志值位,用于界面跳转真正解绑放到出厂设置里面
@@ -3477,6 +3524,20 @@ extern "C" {
                 m_pending_factory_reset = true;
                 ThunderBirdModel::GetInstance()->StartFactoryResetTimer(1); // 2秒后恢复出厂设置
 
+                // 如果是从对话模式(说话/聆听)跳转到解绑警告/绑定成功界面,则先退出对话模式
+                if (currentView == THUNDERBIRD_DIALOGUEVIEW &&
+                    (currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING ||
+                     currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)) {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleBindAndUnbind: 从对话模式跳转解绑警告/绑定成功,先退出对话模式");
+                    StopCountUpTimer();
+                    ThunderBirdPresenter::GetInstance()->SetDialogueing(false);
+                    ln_ws_end_audio_chat();//结束对话
+                    AI_ForceInterrupt();
+                    ln_ws_send_voice_chat_interrupt("退出对话");
+                    OnExitDialogueMode();
+                    do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_AUDIO_DEINIT, NULL, 0);
+                }
+
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_ADJUSTVIEW, ThunderBirdAdjustView::THUNDERBIRD_ADJUSTVIEW_BIND_SUCCESS);
                 if(ThunderBirdAdjustView::GetInstance())
                 {
@@ -3619,6 +3680,8 @@ extern "C" {
             if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
                 ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(true);
             }
+            // 播放结束进入聆听前状态,打开 VAD 识别
+            ln_ws_set_vad_recognition_enabled(true);
             // 启动20秒定时器,时间到就退出对话
             StartCountUpTimer(20);
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackEnd: 启动20秒定时器,时间到就退出对话");
@@ -3708,16 +3771,26 @@ extern "C" {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioRecordingStart: 在哄睡界面(故事模式),忽略录音开始事件");
                 return;
             }
-            if ((currentView == THUNDERBIRD_DIALOGUEVIEW && 
-                currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING) ) {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "录音开始,跳转到聆听状态");
-                view->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
-                // ThunderBirdDialogueView::GetInstance()->IsNormalEnd = false;
-            }
-            // 如果当前在哄睡界面,且不在故事选择状态,则跳转到故事选择状态
-            else {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioRecordingStart: 不满足推送条件");
+            if (currentView == THUNDERBIRD_DIALOGUEVIEW) {
+                if (currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING) {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                        "ThunderBirdModel::HandleAudioRecordingStart: speaking 中收到录音开始,交由 VAD 流程处理,只切换到聆听界面");
+                    auto* mainView = ThunderBirdMainView::GetInstance();
+                    if (mainView && mainView->listenIcon) {
+                        mainView->listenIcon->SetVisible(true);
+                    }
+                    view->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW,
+                                     ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
+                    return;
+                } else if (currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING) {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                        "ThunderBirdModel::HandleAudioRecordingStart: 已在聆听界面,忽略重复的录音开始事件");
+                    return;
+                }
             }
+
+            // 其它界面当前不处理录音开始
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioRecordingStart: 不满足推送条件");
         }
     }
     
@@ -4015,12 +4088,15 @@ extern "C" {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnEnterDialogueMode: 眨眼表情文件不存在: %s", winkingExpressionPath.c_str());
             }
         }
+        // 进入对话且为聆听界面时打开 VAD 识别(仅在此处与播放结束、按键进入聆听时打开)
+        ln_ws_set_vad_recognition_enabled(true);
     }
     
     // 退出对话模式时恢复表情
     void ThunderBirdModel::OnExitDialogueMode()
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitDialogueMode: 开始退出对话模式");
+        ln_ws_set_vad_recognition_enabled(false);
         
         #ifdef SUPPORT_CAT1_SERVICE
         // 退出对话模式时恢复AT+CESQ命令,恢复获取4G信号