From f9ec5595c7cdb7eecc968c71885b172adba36e89 Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Thu, 27 Nov 2025 17:48:30 +0800 Subject: [PATCH] =?utf8?q?ln=EF=BC=9A=E8=93=9D=E7=89=99=E8=AE=BE=E5=A4=87?= =?utf8?q?=E5=88=97=E8=A1=A8ui=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeui/bluetooth/src/BluetoothModel.cpp | 8 +- .../bluetooth/src/Ln_Bluetooth_apiC.cpp | 2 +- .../include/ThunderBirdBlueListAdapter.h | 107 +++++ .../thunderbird/include/ThunderBirdBlueView.h | 22 +- .../src/ThunderBirdBlueListAdapter.cpp | 446 ++++++++++++++++++ .../thunderbird/src/ThunderBirdBlueView.cpp | 216 +++++++-- .../thunderbird/src/ThunderBirdPresenter.cpp | 37 +- .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 4 +- 8 files changed, 795 insertions(+), 47 deletions(-) create mode 100644 code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h create mode 100644 code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp index f5071ed8c..b9c84f74f 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp @@ -146,7 +146,7 @@ void BluetoothModel::Init() BtInitCallBacksEx(); BtInitGatts(); BtInitSpp(); - // InitBtHeadsetEvent(); // 蓝牙ct和tg适配初始化 + InitBtHeadsetEvent(); // 蓝牙ct和tg适配初始化 // PhoneServiceInit(); /* 实验室测试需要,开机开广播 */ @@ -260,7 +260,7 @@ void BluetoothModel::SetUpConnedDevicesList() SetConnedDevicesListClear(); unsigned int connedDevicesNum = 0; bool ret = gap_get_paired_devices_num(&connedDevicesNum); - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Setup GetPariedDevicesNum ret = %d, num = %d", ret, connedDevicesNum); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setup GetPariedDevicesNum ret = %d, num = %d", ret, connedDevicesNum); gap_paired_device_info_t *devInfo = (gap_paired_device_info_t*)malloc(sizeof(gap_paired_device_info_t) *connedDevicesNum); if (devInfo == nullptr) { @@ -908,6 +908,10 @@ static void ACLConnectionFail(const bd_addr_t &bdAddr) unsigned char nameLen = BD_NAME_LEN; bool getNameRet = gap_get_device_name(&bdAddr, caseInfo.deviceName, &nameLen); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "连接断开 deviceName: %s", caseInfo.deviceName); + // 设备名为空不处理 + if(strcmp((const char *)caseInfo.deviceName, "") == 0){ + return; + } if(strcmp((const char *)caseInfo.deviceName, BluetoothModel::GetInstance()->GetLastConnedDeviceName()) == 0){ //亮屏操作 diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp index 512e61f86..abf0b40db 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp @@ -81,7 +81,7 @@ namespace OHOS } else { - results = gap_br_set_inquiry_paramters(DEVICE_MAJOR_CLASS_AUDIO_VIDEO, 10); + results = gap_br_set_inquiry_paramters(0, 20); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置扫描参数 results %d", results); results = gap_br_start_discovery(); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "启动扫描 results %d", results); diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h new file mode 100644 index 000000000..a312cc585 --- /dev/null +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: ThunderBird Bluetooth Device List Adapter + * Author: + * Create: 2024-01-01 + */ +#ifndef THUNDERBIRD_BLUE_LIST_ADAPTER_H +#define THUNDERBIRD_BLUE_LIST_ADAPTER_H + +#include +#include "components/abstract_adapter.h" +#include "components/ui_view_group.h" +#include "components/ui_label.h" +#include "components/ui_image_view.h" +#include "bluetooth/BluetoothModel.h" + +namespace OHOS { + +// 设备列表项类型 +enum class DeviceItemType : uint8_t { + SECTION_HEADER_CONNECTED = 0, // 已连接设备分组标题 + SECTION_HEADER_NEARBY, // 附近设备分组标题 + DEVICE_CONNECTED, // 已连接设备 + DEVICE_NEARBY // 附近的设备 +}; + +// 设备列表项数据结构 +struct DeviceListItem { + DeviceItemType type; + BluetoothCaseInfo deviceInfo; + bool isSelected; +}; + +// 蓝牙设备列表项视图 +class ThunderBirdBlueDeviceItemView : public UIViewGroup { +public: + ThunderBirdBlueDeviceItemView(); + ~ThunderBirdBlueDeviceItemView() override; + + // 设置为设备项 + void SetDeviceInfo(const BluetoothCaseInfo& info, bool isConnected); + // 设置为分组标题 + void SetSectionHeader(const char* title); + // 设置选中状态 + void SetSelected(bool selected); + // 获取设备信息 + BluetoothCaseInfo* GetDeviceInfo(void); + // 检查是否是分组标题 + bool IsSectionHeader(void) const { return isSectionHeader_; } + +private: + void SetupChildViews(); + + UILabel nameLabel_; // 设备名称标签 + UIImageView connectedIcon_; // 已连接图标(小圆点) + UIImageView borderImage_; // 选中边框 + BluetoothCaseInfo deviceInfo_{}; + bool isSelected_{false}; + bool isSectionHeader_{false}; + bool isConnected_{false}; +}; + +// 蓝牙设备列表适配器 +class ThunderBirdBlueListAdapter : public AbstractAdapter { +public: + ThunderBirdBlueListAdapter(); + ~ThunderBirdBlueListAdapter() override; + + UIView *GetView(UIView *inView, int16_t index) override; + uint16_t GetCount() override; + + // 刷新设备列表数据 + void RefreshDeviceData(); + + // 选择操作(按键控制) + void SelectNext(); // 选择下一个设备 + void SelectPrevious(); // 选择上一个设备 + int16_t GetSelectedIndex() const { return selectedIndex_; } + void SetSelectedIndex(int16_t index); + + // 获取当前选中的设备 + BluetoothCaseInfo* GetSelectedDevice(); + + // 获取设备总数(不含分组标题) + uint16_t GetDeviceCount() const; + + // 限制常量 + static constexpr uint16_t MAX_CONNECTED_DEVICES = 1; // 最多显示1个已连接设备 + static constexpr uint16_t MAX_NEARBY_DEVICES = 10; // 最多显示10个附近设备 + +private: + // 构建显示列表 + void BuildDisplayList(); + // 检查索引是否为设备项(非分组标题) + bool IsDeviceItem(int16_t index) const; + // 找到下一个可选的设备项索引 + int16_t FindNextSelectableIndex(int16_t currentIndex, bool forward); + + std::list displayList_; // 显示列表(包含分组标题和设备) + int16_t selectedIndex_{-1}; // 当前选中的索引 + ThunderBirdBlueDeviceItemView* itemView_{nullptr}; +}; + +} // namespace OHOS + +#endif // THUNDERBIRD_BLUE_LIST_ADAPTER_H + diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h index 306ead8f6..7d7ae2ee6 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h @@ -11,6 +11,9 @@ namespace OHOS { + // 前向声明 + class ThunderBirdBlueListAdapter; + class ThunderBirdBlueView { public: @@ -25,6 +28,15 @@ namespace OHOS void RefreshDeviceList(void); void HandleBluetoothViewOperation(int16_t view); void ExecuteDisconnect(void); + + // 按键操作接口(设备列表页面使用) + void OnKeyUp(void); // 音量+键:选择上一个设备 + void OnKeyDown(void); // 音量-键:选择下一个设备 + void OnKeyConfirm(void); // 确认键:连接选中的设备 + + // 获取当前选中的设备索引 + int16_t GetSelectedDeviceIndex(void) const; + enum : int16_t { THUNDERBIRD_BULEVIEW_ENTER = 0, // 配对准备中页面 THUNDERBIRD_BULEVIEW_SREACHING, // 寻找设备 @@ -38,6 +50,9 @@ namespace OHOS }; private: + void InitDeviceListAdapter(void); // 初始化设备列表适配器 + void UpdateDeviceListSelection(void); // 更新设备列表选中状态 + UIViewGroup *group{nullptr}; UILabelExt *TextLabel{nullptr}; UILabelExt *TextLabel_2{nullptr}; @@ -50,8 +65,13 @@ namespace OHOS UIImageView *RemindIcon2{nullptr}; UIImageView *RemindIcon3{nullptr}; UIList *DeviceList{nullptr}; + + // 设备列表适配器 + ThunderBirdBlueListAdapter *deviceListAdapter_{nullptr}; + + // 当前视图状态 + int16_t currentShowView_{-1}; }; } #endif - diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp new file mode 100644 index 000000000..69cab2d20 --- /dev/null +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: ThunderBird Bluetooth Device List Adapter + * Author: + * Create: 2024-01-01 + */ +#include "thunderbird/include/ThunderBirdBlueListAdapter.h" +#include "wearable_log.h" +#include "bts_br_gap.h" + +namespace OHOS { + +// 列表项尺寸常量 +constexpr uint16_t ITEM_WIDTH = 240; +constexpr uint16_t ITEM_HEIGHT = 40; +constexpr uint16_t SECTION_HEADER_HEIGHT = 24; +constexpr uint16_t ITEM_BORDER_WIDTH = 2; +constexpr uint16_t CONNECTED_ICON_SIZE = 8; +constexpr uint16_t LABEL_FONT_SIZE = 18; +constexpr uint16_t SECTION_FONT_SIZE = 14; + +// 颜色定义 +constexpr int64_t COLOR_ITEM_BG = 0xFF4D4D4D; // 设备项背景色(深灰) +constexpr int64_t COLOR_BORDER_SELECTED = 0xFFED6C00; // 选中边框颜色(橙色) +constexpr int64_t COLOR_TEXT_WHITE = 0xFFFFFFFF; // 白色文字 +constexpr int64_t COLOR_TEXT_GRAY = 0xFFCCCCCC; // 灰色文字(分组标题) +constexpr int64_t COLOR_CONNECTED_DOT = 0xFFED6C00; // 已连接指示点颜色(橙色) + +//======================================== +// ThunderBirdBlueDeviceItemView 实现 +//======================================== + +ThunderBirdBlueDeviceItemView::ThunderBirdBlueDeviceItemView() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueDeviceItemView create"); + SetPosition(0, 0, ITEM_WIDTH, ITEM_HEIGHT); + SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); // 透明背景 + SetupChildViews(); +} + +ThunderBirdBlueDeviceItemView::~ThunderBirdBlueDeviceItemView() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueDeviceItemView destroy"); + Remove(&borderImage_); + Remove(&nameLabel_); + Remove(&connectedIcon_); +} + +void ThunderBirdBlueDeviceItemView::SetupChildViews() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetupChildViews"); + + borderImage_.SetPosition(0, 0, ITEM_WIDTH, ITEM_HEIGHT); + borderImage_.SetStyle(STYLE_BACKGROUND_COLOR, COLOR_TEXT_GRAY); + borderImage_.SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE); + borderImage_.SetStyle(STYLE_BORDER_RADIUS, 10); + borderImage_.SetVisible(false); + Add(&borderImage_); + + nameLabel_.SetPosition(20, 0, 200, ITEM_HEIGHT); + nameLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); + nameLabel_.SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); + Add(&nameLabel_); + + // 已连接指示图标(小圆点,右侧) + connectedIcon_.SetPosition(ITEM_WIDTH - 16, (ITEM_HEIGHT - CONNECTED_ICON_SIZE) / 2); + connectedIcon_.Resize(CONNECTED_ICON_SIZE, CONNECTED_ICON_SIZE); + connectedIcon_.SetStyle(STYLE_BACKGROUND_COLOR, COLOR_CONNECTED_DOT); + connectedIcon_.SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE); + connectedIcon_.SetStyle(STYLE_BORDER_RADIUS, CONNECTED_ICON_SIZE / 2); + connectedIcon_.SetVisible(false); + Add(&connectedIcon_); +} + +// 设置设备信息(包括分组标题) +void ThunderBirdBlueDeviceItemView::SetDeviceInfo(const BluetoothCaseInfo& info, bool isConnected) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetDeviceInfo name=%s isConnected=%d", + info.deviceName, isConnected); + + isSectionHeader_ = false; + isConnected_ = isConnected; + (void)memcpy_s(&deviceInfo_, sizeof(BluetoothCaseInfo), &info, sizeof(BluetoothCaseInfo)); + + // 设置设备名称 + nameLabel_.SetText(reinterpret_cast(info.deviceName)); + nameLabel_.SetFont(DEFAULT_VECTOR_FONT_FILENAME, LABEL_FONT_SIZE); + nameLabel_.SetPosition(20, 0, 200, ITEM_HEIGHT); + nameLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); + + + // 显示/隐藏已连接指示 + connectedIcon_.SetVisible(isConnected); + + Invalidate(); +} + +// 设置分组标题 +void ThunderBirdBlueDeviceItemView::SetSectionHeader(const char* title) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetSectionHeader title=%s", title); + + isSectionHeader_ = true; + isConnected_ = false; + + // 设置标题文字 + nameLabel_.SetText(title); + nameLabel_.SetFont(DEFAULT_VECTOR_FONT_FILENAME, SECTION_FONT_SIZE); + nameLabel_.SetPosition(20, 0, 200, ITEM_HEIGHT); + nameLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_BOTTOM,UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); + + // 隐藏已连接指示 + connectedIcon_.SetVisible(false); + + borderImage_.SetVisible(false); + + Invalidate(); +} + +void ThunderBirdBlueDeviceItemView::SetSelected(bool selected) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetSelected=%d isSectionHeader=%d", selected, isSectionHeader_); + + isSelected_ = selected; + + if (isSectionHeader_) { + // 分组标题不显示选中状态 + borderImage_.SetVisible(false); + return; + } + + if (selected) { + // 选中状态:显示橙色边框 + borderImage_.SetVisible(true); + } else { + // 非选中状态:无边框 + borderImage_.SetVisible(false); + } + + Invalidate(); +} + +BluetoothCaseInfo* ThunderBirdBlueDeviceItemView::GetDeviceInfo(void) +{ + return &deviceInfo_; +} + +//======================================== +// ThunderBirdBlueListAdapter 实现 +//======================================== + +ThunderBirdBlueListAdapter::ThunderBirdBlueListAdapter() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueListAdapter create"); + RefreshDeviceData(); +} + +ThunderBirdBlueListAdapter::~ThunderBirdBlueListAdapter() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueListAdapter destroy"); + displayList_.clear(); + if (itemView_ != nullptr) { + delete itemView_; + itemView_ = nullptr; + } +} + +void ThunderBirdBlueListAdapter::RefreshDeviceData() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RefreshDeviceData"); + BuildDisplayList(); + + // 如果列表不为空且没有选中项,默认选中第一个设备项 + if (!displayList_.empty() && selectedIndex_ < 0) { + selectedIndex_ = FindNextSelectableIndex(-1, true); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Default selectedIndex=%d", selectedIndex_); + } +} + +void ThunderBirdBlueListAdapter::BuildDisplayList() +{ + displayList_.clear(); + + BluetoothModel* btModel = BluetoothModel::GetInstance(); + if (btModel == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BluetoothModel nullptr"); + return; + } + + // 获取最后连接的设备地址 + bd_addr_t* lastConnedAddr = btModel->GetLastConnedAddr(); + bool hasConnectedDevice = false; + + // 检查是否有已连接的设备 + if (lastConnedAddr != nullptr) { + // 检查地址是否为全0(表示没有连接) + bool isValidAddr = false; + for (int i = 0; i < BD_ADDR_LEN; i++) { + if (lastConnedAddr->addr[i] != 0) { + isValidAddr = true; + break; + } + } + if (isValidAddr && bt_is_acl_connected(lastConnedAddr)) { + hasConnectedDevice = true; + } + } + + // 获取扫描到的设备列表 + std::list& scanDevices = btModel->GetCase(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "scanDevices size=%d hasConnected=%d", + scanDevices.size(), hasConnectedDevice); + + // 构建显示列表 + uint16_t connectedCount = 0; + uint16_t nearbyCount = 0; + + // 1. 添加已连接设备分组(如果有已连接设备) + if (hasConnectedDevice) { + DeviceListItem headerItem; + headerItem.type = DeviceItemType::SECTION_HEADER_CONNECTED; + headerItem.isSelected = false; + displayList_.push_back(headerItem); + + // 添加已连接的设备 + for (auto& device : scanDevices) { + if (connectedCount >= MAX_CONNECTED_DEVICES) { + break; + } + + // 检查设备是否已连接 + if (bt_is_acl_connected((const bd_addr_t*)&device.addr)) { + DeviceListItem item; + item.type = DeviceItemType::DEVICE_CONNECTED; + item.deviceInfo = device; + item.isSelected = false; + displayList_.push_back(item); + connectedCount++; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Added connected device: %s", device.deviceName); + } + } + } + + // 2. 添加附近设备分组 + DeviceListItem nearbyHeader; + nearbyHeader.type = DeviceItemType::SECTION_HEADER_NEARBY; + nearbyHeader.isSelected = false; + displayList_.push_back(nearbyHeader); + + // 3. 添加附近的设备(未连接的) + for (auto& device : scanDevices) { + if (nearbyCount >= MAX_NEARBY_DEVICES) { + break; + } + + // 跳过已连接的设备 + if (bt_is_acl_connected((const bd_addr_t*)&device.addr)) { + continue; + } + + DeviceListItem item; + item.type = DeviceItemType::DEVICE_NEARBY; + item.deviceInfo = device; + item.isSelected = false; + displayList_.push_back(item); + nearbyCount++; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Added nearby device: %s", device.deviceName); + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BuildDisplayList done: connected=%d, nearby=%d, total=%d", + connectedCount, nearbyCount, displayList_.size()); +} + +uint16_t ThunderBirdBlueListAdapter::GetCount() +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetCount=%d", displayList_.size()); + return static_cast(displayList_.size()); +} + +UIView* ThunderBirdBlueListAdapter::GetView(UIView* inView, int16_t index) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView index=%d inView=%p listSize=%d", + index, inView, displayList_.size()); + + if (index < 0 || index >= static_cast(displayList_.size())) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView index out of range!"); + return nullptr; + } + + ThunderBirdBlueDeviceItemView* item = nullptr; + + if (inView == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Creating new item view"); + item = new ThunderBirdBlueDeviceItemView(); + if (item == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView new item failed!"); + return nullptr; + } + } else { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Reusing existing item view"); + item = static_cast(inView); + } + + // 获取对应索引的数据 + auto it = displayList_.begin(); + std::advance(it, index); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView type=%d", static_cast(it->type)); + + switch (it->type) { + case DeviceItemType::SECTION_HEADER_CONNECTED: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting SECTION_HEADER_CONNECTED"); + item->SetSectionHeader("我的设备"); + break; + case DeviceItemType::SECTION_HEADER_NEARBY: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting SECTION_HEADER_NEARBY"); + item->SetSectionHeader("附近的设备"); + break; + case DeviceItemType::DEVICE_CONNECTED: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting DEVICE_CONNECTED: %s", it->deviceInfo.deviceName); + item->SetDeviceInfo(it->deviceInfo, true); + item->SetSelected(index == selectedIndex_); + break; + case DeviceItemType::DEVICE_NEARBY: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting DEVICE_NEARBY: %s", it->deviceInfo.deviceName); + item->SetDeviceInfo(it->deviceInfo, false); + item->SetSelected(index == selectedIndex_); + break; + default: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unknown type!"); + break; + } + + item->SetViewIndex(index); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView done, returning item=%p", item); + return item; +} + +bool ThunderBirdBlueListAdapter::IsDeviceItem(int16_t index) const +{ + if (index < 0 || index >= static_cast(displayList_.size())) { + return false; + } + + auto it = displayList_.begin(); + std::advance(it, index); + + return (it->type == DeviceItemType::DEVICE_CONNECTED || + it->type == DeviceItemType::DEVICE_NEARBY); +} + +int16_t ThunderBirdBlueListAdapter::FindNextSelectableIndex(int16_t currentIndex, bool forward) +{ + if (displayList_.empty()) { + return -1; + } + + int16_t listSize = static_cast(displayList_.size()); + int16_t nextIndex = currentIndex; + + // 查找下一个可选的设备项 + for (int16_t i = 0; i < listSize; i++) { + if (forward) { + nextIndex++; + if (nextIndex >= listSize) { + nextIndex = 0; // 循环到开头 + } + } else { + nextIndex--; + if (nextIndex < 0) { + nextIndex = listSize - 1; // 循环到末尾 + } + } + + if (IsDeviceItem(nextIndex)) { + return nextIndex; + } + } + + return -1; // 没有找到可选项 +} + +void ThunderBirdBlueListAdapter::SelectNext() +{ + int16_t newIndex = FindNextSelectableIndex(selectedIndex_, true); + if (newIndex >= 0 && newIndex != selectedIndex_) { + selectedIndex_ = newIndex; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SelectNext: selectedIndex=%d", selectedIndex_); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "没有可选择的设备"); + } +} + +void ThunderBirdBlueListAdapter::SelectPrevious() +{ + int16_t newIndex = FindNextSelectableIndex(selectedIndex_, false); + if (newIndex >= 0 && newIndex != selectedIndex_) { + selectedIndex_ = newIndex; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SelectPrevious: selectedIndex=%d", selectedIndex_); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "没有可选择的设备"); + } +} + +void ThunderBirdBlueListAdapter::SetSelectedIndex(int16_t index) +{ + if (IsDeviceItem(index)) { + selectedIndex_ = index; + } +} + +BluetoothCaseInfo* ThunderBirdBlueListAdapter::GetSelectedDevice() +{ + if (selectedIndex_ < 0 || selectedIndex_ >= static_cast(displayList_.size())) { + return nullptr; + } + + auto it = displayList_.begin(); + std::advance(it, selectedIndex_); + + if (it->type == DeviceItemType::DEVICE_CONNECTED || + it->type == DeviceItemType::DEVICE_NEARBY) { + return &(it->deviceInfo); + } + + return nullptr; +} + +uint16_t ThunderBirdBlueListAdapter::GetDeviceCount() const +{ + uint16_t count = 0; + for (const auto& item : displayList_) { + if (item.type == DeviceItemType::DEVICE_CONNECTED || + item.type == DeviceItemType::DEVICE_NEARBY) { + count++; + } + } + return count; +} + +} // namespace OHOS diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp index c3af0eb6f..5ff9d4c7d 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp @@ -1,10 +1,12 @@ #include "thunderbird/include/ThunderBirdBlueView.h" #include "thunderbird/include/ThunderBirdMainView.h" +#include "thunderbird/include/ThunderBirdBlueListAdapter.h" #include "wearable_log.h" #include "common/image_cache_manager.h" #include "custom_utils.h" #include "vibrator_service.h" #include "bluetooth/Ln_Bluetooth_apiC.h" +#include "bluetooth/BluetoothModel.h" namespace OHOS @@ -47,6 +49,7 @@ namespace OHOS if (RemindIcon3 != nullptr) { delete RemindIcon3; RemindIcon3 = nullptr; } if (BackGround != nullptr) { delete BackGround; BackGround = nullptr; } if (DeviceList != nullptr) { delete DeviceList; DeviceList = nullptr; } + if (deviceListAdapter_ != nullptr) { delete deviceListAdapter_; deviceListAdapter_ = nullptr; } } bool ThunderBirdBlueView::EnsureNetAnimator() @@ -55,6 +58,18 @@ namespace OHOS return true; } + void ThunderBirdBlueView::InitDeviceListAdapter(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView::InitDeviceListAdapter"); + if (deviceListAdapter_ == nullptr) { + deviceListAdapter_ = new ThunderBirdBlueListAdapter(); + if (deviceListAdapter_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueListAdapter create failed"); + return; + } + } + } + UIViewGroup *ThunderBirdBlueView::ThunderBirdBlueViewInit(void) { group = new UIViewGroup(); @@ -157,28 +172,33 @@ namespace OHOS DeviceList = new UIList(UIList::VERTICAL); if (DeviceList) { - DeviceList->SetPosition(30, 160, 300, 100); - DeviceList->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); - DeviceList->SetDragACCLevel(5); - DeviceList->SetSwipeACCLevel(200); - DeviceList->SetReboundSize(30); - DeviceList->SetVisible(false); + DeviceList->SetPosition(60, 90, 240, 150); // 调整位置和大小以适应圆形屏幕 + DeviceList->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); // 透明背景 group->Add(DeviceList); } + + // 初始化设备列表适配器 + InitDeviceListAdapter(); + return group; } void ThunderBirdBlueView::Show(int16_t showView) { if (group == nullptr) { return; } + currentShowView_ = showView; + if (TextLabel) { TextLabel->SetVisible(false);} + if (TextLabel_2) { TextLabel_2->SetVisible(false);} if (RemindLabel) { RemindLabel->SetVisible(false);} + if (RemindLabel_2) { RemindLabel_2->SetVisible(false);} + if (RemindLabel_3) { RemindLabel_3->SetVisible(false);} if (RemindIcon) { RemindIcon->SetVisible(false); } - if (RemindIcon2) { RemindIcon2->SetVisible(false); } if (RemindIcon1) { RemindIcon1->SetVisible(false); } if (RemindIcon2) { RemindIcon2->SetVisible(false); } if (RemindIcon3) { RemindIcon3->SetVisible(false); } if (DeviceList) { DeviceList->SetVisible(false); } + switch (showView) { case THUNDERBIRD_BULEVIEW_ENTER: @@ -332,60 +352,70 @@ namespace OHOS } case THUNDERBIRD_BULEVIEW_DEVICE_LIST: { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Show DEVICE_LIST view"); + + // 不显示标题(列表中已有分组标题) if (TextLabel) { - TextLabel->SetPosition(112, 60, 180, 42); - TextLabel->SetText("附近的设备"); - TextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); - TextLabel->SetVisible(true); + TextLabel->SetVisible(false); } if (TextLabel_2) { TextLabel_2->SetVisible(false); } + // 显示设备列表 - if (DeviceList) - { - DeviceList->SetPosition(30, 120, 300, 120); + if (DeviceList != nullptr && deviceListAdapter_ != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting up DeviceList"); + + // 刷新设备列表数据 + deviceListAdapter_->RefreshDeviceData(); + // 确保适配器已设置 + DeviceList->SetAdapter(deviceListAdapter_); + DeviceList->SetStartIndex(0); + DeviceList->SetPosition(60, 70, 240, 170); // 调整位置 DeviceList->SetVisible(true); + DeviceList->RefreshList(); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DeviceList visible, count=%d", + deviceListAdapter_->GetCount()); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DeviceList or adapter is null!"); } if (RemindLabel) { - RemindLabel->SetPosition(44, 275, 272, 25); - RemindLabel->SetText("按 +/- 选择"); + RemindLabel->SetPosition(44, 260, 272, 25); + RemindLabel->SetText("按 +/- 选择 按 确认"); RemindLabel->SetVisible(true); } if (RemindLabel_2) { - RemindLabel_2->SetPosition(109, 310, 142, 25); - RemindLabel_2->SetText("按 确认"); + RemindLabel_2->SetPosition(109, 285, 142, 25); + RemindLabel_2->SetText("长按 退出配对"); RemindLabel_2->SetVisible(true); } - if (RemindLabel_3) - { - RemindLabel_3->SetPosition(109, 335, 142, 25); - RemindLabel_3->SetText("长按 退出配对"); - RemindLabel_3->SetVisible(true); - } if (RemindIcon) { RemindIcon->SetVisible(false); } if (RemindIcon1) { - RemindIcon1->SetPosition(68, 277, 22, 22); + RemindIcon1->SetPosition(68, 262, 22, 22); RemindIcon1->SetSrc("/user/res/volume_up.bin"); RemindIcon1->SetVisible(true); } if (RemindIcon2) { - RemindIcon2->SetPosition(216, 277, 22, 22); + RemindIcon2->SetPosition(183, 262, 22, 22); RemindIcon2->SetSrc("/user/res/volume_up.bin"); RemindIcon2->SetVisible(true); } if (RemindIcon3) { - RemindIcon3->SetPosition(151, 312, 22, 22); + RemindIcon3->SetPosition(151, 287, 22, 22); RemindIcon3->SetSrc("/user/res/volume_up.bin"); RemindIcon3->SetVisible(true); } @@ -411,13 +441,13 @@ namespace OHOS } if (RemindLabel) { - RemindLabel->SetPosition(44, 275, 272, 25); - RemindLabel->SetText("按 返回列表 长按 断开连接"); + RemindLabel->SetPosition(44, 260, 272, 25); + RemindLabel->SetText("按 +/- 选择 按 连接"); RemindLabel->SetVisible(true); } if (RemindLabel_2) { - RemindLabel_2->SetPosition(109, 310, 142, 25); + RemindLabel_2->SetPosition(109, 285, 142, 25); RemindLabel_2->SetText("长按 退出配对"); RemindLabel_2->SetVisible(true); } @@ -429,19 +459,19 @@ namespace OHOS } if (RemindIcon1) { - RemindIcon1->SetPosition(68, 277, 22, 22); + RemindIcon1->SetPosition(68, 262, 22, 22); RemindIcon1->SetSrc("/user/res/volume_up.bin"); RemindIcon1->SetVisible(true); } if (RemindIcon2) { - RemindIcon2->SetPosition(216, 277, 22, 22); + RemindIcon2->SetPosition(183, 262, 22, 22); RemindIcon2->SetSrc("/user/res/volume_up.bin"); RemindIcon2->SetVisible(true); } if (RemindIcon3) { - RemindIcon3->SetPosition(151, 312, 22, 22); + RemindIcon3->SetPosition(151, 287, 22, 22); RemindIcon3->SetSrc("/user/res/volume_up.bin"); RemindIcon3->SetVisible(true); } @@ -577,6 +607,7 @@ namespace OHOS HandleBluetoothViewOperation(showView); return; } + void ThunderBirdBlueView::UpdateTaskReminderText(const char* text) { if (TextLabel) { TextLabel->SetText(text); } @@ -584,12 +615,129 @@ namespace OHOS void ThunderBirdBlueView::RefreshDeviceList(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RefreshDeviceList called"); + if (DeviceList == nullptr) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BluetoothEarListView nullptr"); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DeviceList nullptr!"); + return; + } + + if (deviceListAdapter_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "deviceListAdapter_ nullptr!"); + return; + } + + // 刷新适配器数据 + deviceListAdapter_->RefreshDeviceData(); + + // 确保适配器已设置 + DeviceList->SetAdapter(deviceListAdapter_); + DeviceList->RefreshList(); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RefreshDeviceList done, count=%d", + deviceListAdapter_->GetCount()); + } + + void ThunderBirdBlueView::UpdateDeviceListSelection(void) + { + if (DeviceList == nullptr || deviceListAdapter_ == nullptr) { return; } + + // 刷新列表以更新选中状态显示 DeviceList->RefreshList(); + int16_t selectedIndex = deviceListAdapter_->GetSelectedIndex(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateDeviceListSelection: selectedIndex=%d", selectedIndex); } + + // 按键操作:选择上一个设备(音量+键) + void ThunderBirdBlueView::OnKeyUp(void) + { + if (currentShowView_ != THUNDERBIRD_BULEVIEW_DEVICE_LIST) { + return; + } + + if (deviceListAdapter_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "deviceListAdapter_ nullptr"); + return; + } + + deviceListAdapter_->SelectPrevious(); + UpdateDeviceListSelection(); + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "OnKeyUp: selected=%d", + deviceListAdapter_->GetSelectedIndex()); + } + + // 按键操作:选择下一个设备(音量-键) + void ThunderBirdBlueView::OnKeyDown(void) + { + if (currentShowView_ != THUNDERBIRD_BULEVIEW_DEVICE_LIST) { + return; + } + + if (deviceListAdapter_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "deviceListAdapter_ nullptr"); + return; + } + + deviceListAdapter_->SelectNext(); + UpdateDeviceListSelection(); + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "OnKeyDown: selected=%d", + deviceListAdapter_->GetSelectedIndex()); + } + + // 按键操作:确认连接选中的设备 + void ThunderBirdBlueView::OnKeyConfirm(void) + { + if (currentShowView_ != THUNDERBIRD_BULEVIEW_DEVICE_LIST) { + return; + } + + if (deviceListAdapter_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "deviceListAdapter_ nullptr"); + return; + } + + BluetoothCaseInfo* selectedDevice = deviceListAdapter_->GetSelectedDevice(); + if (selectedDevice == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "No device selected"); + return; + } + + WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "OnKeyConfirm: connecting to %s", + selectedDevice->deviceName); + + // 设置临时MAC值并发起连接 + BluetoothModel::GetInstance()->SetTempMacValue(selectedDevice); + BluetoothModel::GetInstance()->SetTagScanDeviceClicked(true); + + // 发起连接 + int ret = BluetoothModel::GetInstance()->ConnectRemoteDevice( + (const bd_addr_t*)&selectedDevice->addr); + + if (ret != 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice failed: %d", ret); + // 可以在这里显示连接失败提示 + if(ThunderBirdMainView::GetInstance()) { + int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); + ThunderBirdMainView::GetInstance()->ChangeView(currentView, + THUNDERBIRD_BLUEVIEW, + ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED); + } + } + } + + // 获取当前选中的设备索引 + int16_t ThunderBirdBlueView::GetSelectedDeviceIndex(void) const + { + if (deviceListAdapter_ == nullptr) { + return -1; + } + return deviceListAdapter_->GetSelectedIndex(); + } + // 处理蓝牙视图操作 void ThunderBirdBlueView::HandleBluetoothViewOperation(int16_t view) { diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp index 57363661f..6d16222cf 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp @@ -345,6 +345,31 @@ namespace OHOS // } // return true; // } + + // 处理设备列表功能 + if (keyState == InputDevice::STATE_RELEASE && screenState == 0 ) + { + if(currentView == THUNDERBIRD_BLUEVIEW ) + { + if(currentSubView == ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST) + { + // 处理设备列表功能 + if(ThunderBirdBlueView::GetInstance()) + ThunderBirdBlueView::GetInstance()->OnKeyConfirm();// 点击确认键:确认选择当前设备 + } + else if(currentSubView == ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS) + { + //跳转到断连询问界面 + ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM); + } + else if(currentSubView == ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM) + { + //执行断连操作 + ThunderBirdBlueView::GetInstance()->ExecuteDisconnect(); + } + } + return true; + } // 短按FUNC键(息屏状态下) if (keyState == InputDevice::STATE_PRESS && screenState == 0 ) { @@ -816,13 +841,8 @@ namespace OHOS //蓝牙已断开,返回搜索界面,提示用户重新搜索 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW); break; - case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS: - //跳转到断连询问界面 - ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM); - break; - case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM: - //执行断连操作 - ThunderBirdBlueView::GetInstance()->ExecuteDisconnect(); + case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST: + ThunderBirdBlueView::GetInstance()->OnKeyUp();// 音量+键:选择上一个设备 break; } } @@ -841,6 +861,9 @@ namespace OHOS //返回设备列表 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST); break; + case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST: + ThunderBirdBlueView::GetInstance()->OnKeyDown();// 音量-键:选择下一个设备 + break; } } else if(keyType == KEY_TYPE_FUNC) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index 4fb245df0..2c5bb2b7f 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -1660,8 +1660,8 @@ static uint32_t ln_bluetooth_status_report_at(uint8_t *para, uint32_t paraLen, c } printf("+LN_BLUETOOTH_STATUS_REPORT: OK\n"); printf("[LN][BLUETOOTH_STATUS_REPORT] bluetoothStatus=%s\n", bluetoothStatus); - do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus)); - // push_bluetooth_connect_notification(bluetoothStatus); + // do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus)); + push_bluetooth_connect_notification(bluetoothStatus); return ERRCODE_SUCC; } /* 格式化打印蓝牙地址 */ -- 2.17.1