You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 blueNRG蓝牙设备名称更新后iOS端显示异常问题咨询

为什么iOS设备必须连接断开蓝牙设备后才会显示更新后的名称?

这个问题我之前帮朋友排查过类似的,本质是iOS系统层面的蓝牙缓存机制,再加上你当前设备端的名称更新逻辑没做全导致的,我来拆解清楚:

核心原因:iOS的蓝牙广告数据缓存

iOS的CoreBluetooth框架会在系统级别缓存它发现的蓝牙设备的关键信息——包括广播包(Advertisement Data)里的设备名称、设备UUID等。这个缓存不是跟着APP走的,是存在系统蓝牙服务里的:

  • 当你的设备第一次被iPhone发现时,iOS会把当时广播的oldName存进缓存;
  • 哪怕你后续更新了设备的GATT名称特征,只要设备广播包没同步更新新名称,iOS在扫描时还是会优先用缓存里的旧名称,不会主动去校验广播包的新内容;
  • 只有当iPhone与设备建立连接后,CoreBluetooth会从GATT服务里获取到最新的设备名称,这时候系统才会更新缓存里的名称数据,下次扫描时就会显示新名称了。

你的实验场景也完全贴合这个逻辑:

  • iPhone1连接断开后,系统缓存更新为newName,所以后续扫描能看到新名称;
  • iPhone2从未连接过,系统一直用第一次缓存的oldName,直到连接后才触发缓存更新。

你设备端的遗漏:只更新了GATT特征,没更新广播包名称

你现在只通过aci_gatt_update_char_value更新了GATT服务里的设备名称特征,但蓝牙设备的广播包和GATT特征是两个独立的名称来源:

  • iOS扫描时优先读取广播包里的Local Name字段;
  • 只有当广播包里没有这个字段,或者连接后,才会读取GATT里的设备名称特征。

所以要解决这个问题,你需要在设备端同时更新两个地方的名称:

1. 保留现有GATT特征更新逻辑(已实现)

继续使用你当前的代码更新GATT设备名称特征:

aci_gatt_update_char_value(service_handle, dev_name_char_handle, 0, strlen(name), (uint8_t *)name);

2. 同步更新广播包的本地名称

在blueNRG固件里,需要调用对应API更新广播数据中的本地名称,比如用aci_gap_update_advertising_data或者重新设置可发现模式时传入新名称:

// 假设name是你要设置的新名称
uint8_t adv_data[31];
uint8_t adv_len = 0;
// 构造包含本地名称的广播数据
adv_data[adv_len++] = 1 + strlen(name);
adv_data[adv_len++] = 0x09; // 标识这是本地名称的AD类型
memcpy(&adv_data[adv_len], name, strlen(name));
adv_len += strlen(name);
// 更新广播数据
aci_gap_update_advertising_data(adv_len, adv_data);
// 或者重新设置可发现模式,确保广播时携带新名称
aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE, adv_len, adv_data, 0, NULL, 0, 0);

这样设备重启后,广播包会直接发送新名称,iOS扫描时就能直接获取到newName,不需要先连接断开了。

额外说明:iOS缓存的特殊情况

如果遇到缓存顽固不更新的极端情况,用户可以在iPhone的「设置-蓝牙」里找到设备,点击「忽略此设备」,再重新扫描就能获取最新的广播数据,但这是用户端的操作,我们作为设备开发者,还是应该通过同步更新广播和GATT名称来从根源解决问题。

内容的提问来源于stack exchange,提问作者Vitaly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:14:22