HAND_AUDIO_RECORDING_END_NOTIFY, // 录音结束通知
HAND_NPC_EMOTION_CHANGE_NOTIFY, // npc表情变化通知
HAND_TIMELINE_STATUS_CHANGE_NOTIFY, // 时间线状态变化通知
+ HAND_UPGRADE_DESCRIPTION_NOTIFY, // 升级描述通知
MAX_NUM_HANDLER,
} UiServiceMsgId;
void HandleDownloadProgress(int progress);
void HandleDownloadEta(int seconds);
void HandleDownloadFail(int type);
+
+ void SetUpgradeDescription(const std::string& description);
+ std::string GetUpgradeDescription() const;
private:
OtaModel();
virtual ~OtaModel();
// 夜间更新状态
bool m_nightUpdateEnabled; // 夜间更新是否启用
+
+ std::string m_upgradeDescription; // 升级描述
};
}
UtilsSetValue("night_update_enabled", "0");
WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "OtaModel: Night update status cleared from KV storage");
}
+
+ void OtaModel::SetUpgradeDescription(const std::string& description)
+ {
+ m_upgradeDescription = description;
+ }
+
+ std::string OtaModel::GetUpgradeDescription() const
+ {
+ return m_upgradeDescription;
+ }
}
*/
#include "ota/include/OtaNormalView.h"
#include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
#include "wearable_log.h"
namespace OHOS
LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
- LittleTextLabel->SetText("全新功能已推出,现在Amby可以哄你睡觉");
+ LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
LittleTextLabel->SetVisible(true);
group->Add(LittleTextLabel);
}
*/
#include "ota/include/OtaObviousView.h"
#include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
#include "wearable_log.h"
namespace OHOS
LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
- LittleTextLabel->SetText("全新功能已推出,现在Amby可以哄你睡觉");
+ LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
LittleTextLabel->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
LittleTextLabel->SetVisible(true);
group->Add(LittleTextLabel);
*/
#include "ota/include/OtaUpdateNowView.h"
#include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
#include "wearable_log.h"
namespace OHOS
LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
- LittleTextLabel->SetText("为保障您的产品安全,部分功能将在更新后恢复使用");
+ LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
LittleTextLabel->SetVisible(true);
group->Add(LittleTextLabel);
}
static void HandAudioRecordingEndNotify(Request *request);
static void HandNpcEmotionChangeNotify(Request *request);
static void HandTimelineStatusChangeNotify(Request *request);
+static void HandUpgradeDescriptionNotify(Request *request);
// 消息处理程序项数组(每个消息类型对应一个处理函数,函数名以 Handle 开头)
MsgHandlerEntry msgHandlers[] = {
{HANDLE_JUMP_OTA_VIEW, HandleJumpOtaView},
{HAND_AUDIO_RECORDING_END_NOTIFY,HandAudioRecordingEndNotify},
{HAND_NPC_EMOTION_CHANGE_NOTIFY,HandNpcEmotionChangeNotify},
{HAND_TIMELINE_STATUS_CHANGE_NOTIFY,HandTimelineStatusChangeNotify},
+ {HAND_UPGRADE_DESCRIPTION_NOTIFY,HandUpgradeDescriptionNotify},
};
/* -------------------------------------------------------------------------- */
void ScreenTurnOn(int32_t timeout)
}
});
}
+
+void HandUpgradeDescriptionNotify(Request *request)
+{
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandUpgradeDescriptionNotify msg_id = %d", request->msgId);
+ std::string description(static_cast<char*>(request->data), request->len);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandUpgradeDescriptionNotify description = %s", description.c_str());
+ GraphicService::GetInstance()->PostGraphicEvent(
+ std::bind(&OHOS::OtaModel::SetUpgradeDescription,OHOS::OtaModel::GetInstance(), description.c_str()));
+}
/* -------------------------------------------------------------------------- */
#ifdef __cplusplus
}
return;
}
+ /*
+ {
+ "errorCode": null,
+ "message": null,
+ "data": {
+ "updateId": 123, 升级任务ID
+ "sourceVersion": "1.0.0", 源版本号
+ "targetVersion": "1.1.0", 目标版本号
+ "updateType": 1, 升级类型,0:紧急修复,1:重要更新,2:普通更新
+ "packageId": 456, 升级包ID
+ "packageUrl": "https://example.com/firmware/update_1.1.0.bin", 升级包下载URL
+ "packageMd5": "a1b2c3d4e5f6789012345678901234567890", 升级包MD5校验值
+ "packageSize": 1048576, 升级包大小(字节)
+ "description": "升级描述" 升级描述
+ }
+ }
+ */
+
+ cJSON *updateId = cJSON_GetObjectItem(data, "updateId");
+ cJSON *sourceVersion = cJSON_GetObjectItem(data, "sourceVersion");
cJSON *targetVersion = cJSON_GetObjectItem(data, "targetVersion");
cJSON *updateType = cJSON_GetObjectItem(data, "updateType");
+ cJSON *packageId = cJSON_GetObjectItem(data, "packageId");
cJSON *packageUrl = cJSON_GetObjectItem(data, "packageUrl");
cJSON *packageMd5 = cJSON_GetObjectItem(data, "packageMd5");
cJSON *packageSize = cJSON_GetObjectItem(data, "packageSize");
+ cJSON *description = cJSON_GetObjectItem(data, "description");
uapi_ln_set_ota_package_size(packageSize ? (int)packageSize->valuedouble : 0);
if (!(targetVersion && cJSON_IsString(targetVersion) && updateType && (cJSON_IsNumber(updateType) || cJSON_IsString(updateType))))
else if (cJSON_IsString(updateType)) ut = atoi(updateType->valuestring);
g_ln_last_update_type = ut;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] task parsed: targetVersion=%s updateType=%d url=%s md5=%s",
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] task parsed: targetVersion=%s updateType=%d url=%s md5=%s description=%s",
targetVersion->valuestring, ut,
(packageUrl && cJSON_IsString(packageUrl)) ? packageUrl->valuestring : "<null>",
- (packageMd5 && cJSON_IsString(packageMd5)) ? packageMd5->valuestring : "<null>");
+ (packageMd5 && cJSON_IsString(packageMd5)) ? packageMd5->valuestring : "<null>",
+ (description && cJSON_IsString(description)) ? description->valuestring : "<null>");
/* 记录必要字段供后续 AT^LN_OTA_DOWNLOAD 使用 */
if (g_ln_last_target_version) { free(g_ln_last_target_version); g_ln_last_target_version = NULL; }
if (g_ln_last_package_url) { free(g_ln_last_package_url); g_ln_last_package_url = NULL; }
if (g_ln_last_package_size < 0) g_ln_last_package_size = 0;
}
- if (ut == 1)
+ if (description && cJSON_IsString(description)) {
+ push_upgrade_description_notification(description->valuestring);
+ } else {
+ push_upgrade_description_notification("");
+ }
+
+ if (ut == 0)
{
/* 强制升级:直接触发下载 */
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] force upgrade: trigger download(强制升级:直接触发下载)");
push_ota_status(OTA_UI_STATUS_FORCE_START);
}
- else if (ut == 0)
+ else
{
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] optional upgrade: waiting for user confirmation(可选升级:等待用户确认)");
push_ota_status(OTA_UI_STATUS_OPTIONAL_START);
}
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] unknown updateType, skip");
- }
cJSON_Delete(root);
free(text);
#include "wearable_log.h"
#include "ai_media.h"
#include "audio_stream_player.h"
+#include "ln_audio_simple.h"
ScheduleReminder g_schedule_reminder = {0};
ScheduleReminderConfig g_schedule_reminder_config = {0};
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] vibration:不执行震动\n");
}
// 从文件中读取数据放到音频流内
- play_mp3_audio_from_file(LN_REMINDER_AUDIO_FILE);
+ // play_mp3_audio_from_file(LN_REMINDER_AUDIO_FILE);
// 下载成功后
// ln_audio_player_play_file(LN_REMINDER_AUDIO_FILE);
+ ln_audio_simple_play(LN_REMINDER_AUDIO_FILE);
}
else
{
${ROOT_DIR}/middleware/services/media/foundation/sample/wrapper
${ROOT_DIR}/middleware/services/media/foundation/utils/include
${ROOT_DIR}/application/wearable/ln/nativeapp/nativeui/
+${ROOT_DIR}/open_source/openharmony/foundation/multimedia/player/interfaces/kits/
+${ROOT_DIR}/middleware/services/gui/uikit/surface/interfaces/kits/
+${ROOT_DIR}/open_source/openharmony/drivers/peripheral/display/interfaces/include/
)
set(AI_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/audio_stream_player.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ln_api_interface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/audio_stream_player.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/ln_audio_simple.cpp
)
set(SOURCES
(void)snprintf(payload, sizeof(payload) - 1, "%s|%s", d, e);
SendMsgToUIService(HAND_TIMELINE_STATUS_CHANGE_NOTIFY, 0, (void *)payload, (int32_t)strlen(payload));
}
+
+//推送升级描述
+void push_upgrade_description_notification(const char *description)
+{
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[UPGRADE_DESCRIPTION] description=%s", description);
+ SendMsgToUIService(HAND_UPGRADE_DESCRIPTION_NOTIFY, 0, (void *)description, (int32_t)strlen(description));
+}
#ifdef __cplusplus
};
#endif
\ No newline at end of file
void push_npc_emotion_change_notification(const char *emotion);
//通知时间线状态变化
void push_timeline_status_change_notification(const char *description, const char *emotion);
+//推送升级描述
+void push_upgrade_description_notification(const char *description);
#ifdef __cplusplus
}
#endif
--- /dev/null
+#include <memory>
+#include <map>
+/* C 接口头文件 */
+#include "ln_audio_simple.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+/* 引入播放器相关头文件 */
+#include "player.h"
+#include "source.h"
+#include "audio_manager.h"
+#include <audio_base_type.h>
+#include <audio_player_service.h>
+#include <custom_utils.h>
+#include <los_base.h>
+
+using OHOS::Media::Player;
+using OHOS::Media::Source;
+using namespace OHOS::Media;
+using namespace ::Audio;
+using Audio::AudioManager;
+
+
+
+typedef struct
+{
+ std::shared_ptr<Player> player;
+ std::shared_ptr<Source> source;
+ std::map<std::string, std::string> header;
+
+ AudioSession sessionId;
+ std::shared_ptr<AudioInterrupt> interrupt;
+ std::shared_ptr<InterruptListener> interruptListener;
+
+ bool audio_initialized;
+ bool is_activate_audio_interrupt;
+ bool is_playing;
+ bool is_paused;
+} ln_audio_simple_impl_t;
+
+static ln_audio_simple_impl_t g_simple = {0};
+
+class SimpleSingleInterruptListener : public InterruptListener
+{
+public:
+ SimpleSingleInterruptListener(ln_audio_simple_impl_t *impl) : impl_(impl) {}
+
+ void OnInterrupt(int32_t type, int32_t hint) override
+ {
+ if (!impl_) return;
+ if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE)
+ {
+ if (impl_->is_playing && impl_->player)
+ {
+ impl_->player->Pause();
+ impl_->is_paused = true;
+ }
+ }
+ else if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME)
+ {
+ if (impl_->is_playing && impl_->player && impl_->is_paused)
+ {
+ impl_->player->Play();
+ impl_->is_paused = false;
+ }
+ }
+ else if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP)
+ {
+ if (impl_->is_playing && impl_->player)
+ {
+ impl_->player->Stop();
+ impl_->is_playing = false;
+ }
+ }
+ }
+
+private:
+ ln_audio_simple_impl_t *impl_;
+};
+
+static bool AudioInitOnce(void)
+{
+ if (g_simple.audio_initialized)
+ return true;
+
+ AudioManager &amInstance = AudioManager::GetInstance();
+ if (!amInstance.Initialize())
+ {
+ printf("[LN_AUDIO_SIMPLE] AudioManager Initialize failed\n");
+ return false;
+ }
+
+ g_simple.player = std::make_shared<Player>();
+ if (!g_simple.player)
+ {
+ printf("[LN_AUDIO_SIMPLE] Player create failed\n");
+ return false;
+ }
+
+ g_simple.audio_initialized = true;
+ g_simple.is_activate_audio_interrupt = false;
+ g_simple.is_playing = false;
+ g_simple.is_paused = false;
+ return true;
+}
+
+static bool EnsureAudioInterrupt()
+{
+ if (g_simple.is_activate_audio_interrupt)
+ return true;
+
+ AudioManager &amInstance = AudioManager::GetInstance();
+ g_simple.sessionId = amInstance.MakeSessionId();
+ if (g_simple.sessionId == AUDIO_SESSION_ID_NONE)
+ {
+ printf("[LN_AUDIO_SIMPLE] MakeSessionId failed\n");
+ return false;
+ }
+
+ g_simple.interruptListener = std::make_shared<SimpleSingleInterruptListener>(&g_simple);
+ g_simple.interrupt = std::make_shared<AudioInterrupt>();
+ g_simple.interrupt->streamType = AUDIO_STREAM_ALARM_CLOCK;
+ g_simple.interrupt->sessionID = g_simple.sessionId;
+ g_simple.interrupt->interruptListener = g_simple.interruptListener;
+
+ if (amInstance.ActivateAudioInterrupt(*g_simple.interrupt) == INTERRUPT_FAILED)
+ {
+ printf("[LN_AUDIO_SIMPLE] ActivateAudioInterrupt failed\n");
+ return false;
+ }
+
+ g_simple.is_activate_audio_interrupt = true;
+ return true;
+}
+
+static void ClearAudioInterrupt()
+{
+ if (g_simple.is_activate_audio_interrupt && g_simple.interrupt && g_simple.sessionId != AUDIO_SESSION_ID_NONE)
+ {
+ AudioManager &amInstance = AudioManager::GetInstance();
+ amInstance.DeactivateAudioInterrupt(*g_simple.interrupt);
+ g_simple.is_activate_audio_interrupt = false;
+ }
+ g_simple.interrupt.reset();
+ g_simple.interruptListener.reset();
+}
+
+extern "C" {
+
+int ln_audio_simple_play(const char *file_path)
+{
+ if (!file_path || file_path[0] == '\0')
+ {
+ printf("[LN_AUDIO_SIMPLE] invalid file path\n");
+ return -1;
+ }
+
+ if (!AudioInitOnce())
+ return -2;
+
+ // 若正在播放,先停止
+ (void)ln_audio_simple_stop();
+
+ // 设置音频源
+ g_simple.source = std::make_shared<Source>(file_path, g_simple.header);
+ if (!g_simple.source)
+ {
+ printf("[LN_AUDIO_SIMPLE] create Source failed\n");
+ return -3;
+ }
+
+ int32_t ret;
+ ret = g_simple.player->SetSource(*g_simple.source);
+ if (ret != 0)
+ {
+ printf("[LN_AUDIO_SIMPLE] SetSource failed: %d\n", ret);
+ g_simple.player->Reset();
+ return -4;
+ }
+
+ g_simple.player->EnableSingleLooping(false);
+ g_simple.player->SetAudioStreamType(AUDIO_STREAM_ALARM_CLOCK);
+
+ ret = g_simple.player->Prepare();
+ if (ret != 0)
+ {
+ printf("[LN_AUDIO_SIMPLE] Prepare failed: %d\n", ret);
+ g_simple.player->Reset();
+ return -5;
+ }
+
+ if (!EnsureAudioInterrupt())
+ {
+ g_simple.player->Reset();
+ return -6;
+ }
+
+ ret = g_simple.player->SetAudioSessionId(g_simple.sessionId);
+ if (ret != 0)
+ {
+ printf("[LN_AUDIO_SIMPLE] SetAudioSessionId failed: %d\n", ret);
+ g_simple.player->Reset();
+ ClearAudioInterrupt();
+ return -7;
+ }
+
+ ret = g_simple.player->Play();
+ if (ret != 0)
+ {
+ printf("[LN_AUDIO_SIMPLE] Play failed: %d\n", ret);
+ g_simple.player->Stop();
+ g_simple.player->Reset();
+ ClearAudioInterrupt();
+ return -8;
+ }
+
+ g_simple.is_playing = true;
+ g_simple.is_paused = false;
+ printf("[LN_AUDIO_SIMPLE] started: %s\n", file_path);
+ return 0;
+}
+
+int ln_audio_simple_stop(void)
+{
+ if (!g_simple.player)
+ return 0;
+
+ int32_t state = 0;
+ (void)g_simple.player->GetPlayerState(state);
+
+ if (state == PLAYER_STARTED || state == PLAYER_PLAYBACK_COMPLETE)
+ {
+ (void)g_simple.player->Stop();
+ (void)g_simple.player->Reset();
+ }
+ else if (state == PLAYER_PAUSED || state == PLAYER_IDLE)
+ {
+ (void)g_simple.player->Reset();
+ }
+ else
+ {
+ (void)g_simple.player->Stop();
+ (void)g_simple.player->Reset();
+ }
+
+ ClearAudioInterrupt();
+
+ g_simple.is_playing = false;
+ g_simple.is_paused = false;
+ return 0;
+}
+
+bool ln_audio_simple_is_playing(void)
+{
+ return g_simple.is_playing;
+}
+
+} // extern "C"
+
+
--- /dev/null
+/*
+ * 简易音频播放接口(C)
+ * 设计目标:简单、稳定,用一行代码播放单个本地音频文件
+ * 用法示例:
+ * ln_audio_simple_play("/user/audio/demo.mp3");
+ * // ... 需要中断播放时:
+ * ln_audio_simple_stop();
+ * // 查询是否还在播放:
+ * // if (ln_audio_simple_is_playing()) { ... }
+ */
+
+#ifndef LN_AUDIO_SIMPLE_H
+#define LN_AUDIO_SIMPLE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * 播放本地音频文件(目前支持常见压缩音频,如 mp3,由底层流式播放器解码)
+ * 参数:
+ * file_path - 音频文件的绝对路径
+ * 返回:
+ * 0 成功启动播放(异步)
+ * <0 失败
+ */
+int ln_audio_simple_play(const char *file_path);
+
+/*
+ * 主动停止播放(同步停止,确保资源释放)
+ * 返回:0 成功,<0 失败
+ */
+int ln_audio_simple_stop(void);
+
+/*
+ * 查询当前是否处于播放中
+ */
+bool ln_audio_simple_is_playing(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_AUDIO_SIMPLE_H */
+
+