最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android BLE 的 notify 和 indicate區(qū)別解析

 更新時(shí)間:2026年04月27日 10:07:35   作者:JJay.  
這篇文章主要講解了BLE協(xié)議中notify和indicate的區(qū)別,以及在項(xiàng)目中如何選擇使用它們,notify更適合高頻、連續(xù)、允許局部丟失的數(shù)據(jù),而indicate更適合關(guān)鍵、低頻、必須確認(rèn)的狀態(tài),正確選擇使用notify或indicate可以提高項(xiàng)目的穩(wěn)定性和性能

做 BLE 的時(shí)候,很多人第一次看到 notifyindicate,會(huì)覺(jué)得它們看起來(lái)差不多。

表面上也確實(shí)差不多。兩者都是設(shè)備主動(dòng)往手機(jī)推數(shù)據(jù),Android 端通常都會(huì)在 onCharacteristicChanged() 里收到回調(diào)。你如果只看上層現(xiàn)象,很容易把它們理解成“兩個(gè)名字不同的通知模式”。

但真寫(xiě)項(xiàng)目,尤其是設(shè)備協(xié)議稍微復(fù)雜一點(diǎn)以后,notifyindicate 的區(qū)別并不只是名詞差異。它們背后對(duì)應(yīng)的是兩種不同的可靠性模型,而這個(gè)差異會(huì)直接影響你的收消息穩(wěn)定性、吞吐量、延遲,甚至?xí)绊懩愕降自撛趺丛O(shè)計(jì)協(xié)議。

所以這篇不講太泛的 BLE 概念,就講一個(gè)實(shí)際問(wèn)題:notifyindicate 到底差在哪,Android 端該怎么理解,項(xiàng)目里又該怎么選。

先說(shuō)結(jié)論

如果只壓成一句話(huà):

  • notify 更快,更輕,但不保證每條都被確認(rèn)
  • indicate 更穩(wěn),更重,每一條都需要對(duì)端確認(rèn)

這句話(huà)基本對(duì),但還不夠你寫(xiě)項(xiàng)目。

因?yàn)?Android 開(kāi)發(fā)里最容易誤判的地方,不是“不知道它們有區(qū)別”,而是不知道這個(gè)區(qū)別會(huì)影響協(xié)議設(shè)計(jì)。

從 BLE 協(xié)議語(yǔ)義看

BLE GATT 里,characteristic 的值變化可以通過(guò) server 主動(dòng)推送給 client。這里主要有兩種方式:

  • Notification
  • Indication

Notification 的特點(diǎn)是 server 發(fā)出去就發(fā)出去了,不要求 client 回一個(gè)鏈路層確認(rèn)。
Indication 的特點(diǎn)是 server 發(fā)出去以后,要等 client 確認(rèn),這條鏈路才算完成。

也就是說(shuō),indicate 不是比 notify “高級(jí)一點(diǎn)”,而是它本身就多了一層確認(rèn)語(yǔ)義。

這個(gè)差異非常關(guān)鍵。

因?yàn)樗馕吨?/p>

  • notify 更適合高頻狀態(tài)流
  • indicate 更適合關(guān)鍵狀態(tài)或關(guān)鍵事件

如果你把高頻數(shù)據(jù)流全做成 indicate,鏈路會(huì)被確認(rèn)機(jī)制拖慢。
如果你把關(guān)鍵確認(rèn)消息全做成 notify,鏈路又可能在邊界場(chǎng)景下不夠穩(wěn)。

Android 端為什么看起來(lái)差不多

很多人會(huì)混淆,是因?yàn)?Android 端最后收消息的回調(diào)長(zhǎng)得一樣:

override fun onCharacteristicChanged(
    gatt: BluetoothGatt,
    characteristic: BluetoothGattCharacteristic,
    value: ByteArray
) {
    Log.d("BLE", "received=${value.joinToString(" ") { "%02X".format(it) }}")
}

不管底層是 notify 還是 indicate,最終都可能進(jìn)這個(gè)回調(diào)。

所以如果你只從 Android API 表層去看,會(huì)覺(jué)得它們沒(méi)有本質(zhì)區(qū)別。
但這只是因?yàn)?Android 把“收到值變化”統(tǒng)一封裝成了同一個(gè)回調(diào),不代表底層行為一樣。

真正的差異發(fā)生在設(shè)備側(cè)和鏈路語(yǔ)義上,而不是發(fā)生在你收到回調(diào)的那一刻。

打開(kāi) notify 和 indicate,代碼為什么也很像

在 Android 端,開(kāi)啟兩者的流程也非常接近。通常都是兩步:

  1. 本地調(diào)用 setCharacteristicNotification()
  2. 寫(xiě) CCCD descriptor

關(guān)鍵差別在于你給 CCCD 寫(xiě)的值不同。

開(kāi)啟 notify

val characteristic = service.getCharacteristic(NOTIFY_UUID)
gatt.setCharacteristicNotification(characteristic, true)
val cccd = characteristic.getDescriptor(
    UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
)
cccd.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
gatt.writeDescriptor(cccd)

開(kāi)啟 indicate

val characteristic = service.getCharacteristic(INDICATE_UUID)
gatt.setCharacteristicNotification(characteristic, true)
val cccd = characteristic.getDescriptor(
    UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
)
cccd.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
gatt.writeDescriptor(cccd)

真正的區(qū)別就在:

  • ENABLE_NOTIFICATION_VALUE
  • ENABLE_INDICATION_VALUE

也就是說(shuō),Android 端不是通過(guò)不同回調(diào)區(qū)分,而是通過(guò)寫(xiě)不同的 descriptor 值去告訴設(shè)備:你應(yīng)該用哪種方式推數(shù)據(jù)。

什么時(shí)候更適合用 notify

notify 更適合這些場(chǎng)景:

  • 高頻傳感器數(shù)據(jù)
  • 實(shí)時(shí)狀態(tài)流
  • 音頻或流式數(shù)據(jù)
  • 變化很快、允許丟個(gè)別包的場(chǎng)景

原因很簡(jiǎn)單,它輕。

沒(méi)有每條都要確認(rèn)的開(kāi)銷(xiāo),設(shè)備可以更快地往上推。
所以如果你有一個(gè)設(shè)備每隔幾十毫秒就上報(bào)一次狀態(tài),或者持續(xù)推一段連續(xù)數(shù)據(jù),通常更適合 notify

比如耳機(jī)、電量變化、佩戴狀態(tài)流、某些實(shí)時(shí)遙測(cè)數(shù)據(jù),這類(lèi)都更適合用 notify

但它的問(wèn)題也很明確:如果你把所有東西都丟給 notify,你就默認(rèn)接受一個(gè)前提,鏈路不會(huì)幫你逐條確認(rèn)。

所以 notify 適合“多、快、可持續(xù)”的數(shù)據(jù),不適合“必須一條不丟”的關(guān)鍵控制確認(rèn)。

什么時(shí)候更適合用 indicate

indicate 更適合這些場(chǎng)景:

  • 關(guān)鍵狀態(tài)變更確認(rèn)
  • 必須可靠到達(dá)的結(jié)果回包
  • 低頻但重要的控制響應(yīng)
  • 某些升級(jí)、配對(duì)、鑒權(quán)類(lèi)消息

因?yàn)?indicate 的特點(diǎn)不是快,而是它自帶確認(rèn)語(yǔ)義。

如果設(shè)備要告訴 App 一個(gè)特別關(guān)鍵的狀態(tài),比如:

  • 配置寫(xiě)入成功
  • 某個(gè)模式切換已完成
  • 升級(jí)狀態(tài)切換
  • 某一步校驗(yàn)通過(guò)

這種時(shí)候 indicate 往往比 notify 更合理。

因?yàn)檫@類(lèi)消息一旦漏掉,App 側(cè)狀態(tài)機(jī)就可能直接走歪。

真正的區(qū)別不是“哪個(gè)更好”,而是“你在傳什么”

很多 BLE 項(xiàng)目寫(xiě)得不穩(wěn),本質(zhì)上不是不會(huì)調(diào) API,而是沒(méi)有把數(shù)據(jù)按語(yǔ)義分層。

比如把高頻狀態(tài)流做成 indicate,結(jié)果整條鏈路被確認(rèn)機(jī)制拖得很慢。
或者把關(guān)鍵確認(rèn)消息做成 notify,結(jié)果某次狀態(tài)切換沒(méi)收到,App 側(cè)以為設(shè)備沒(méi)響應(yīng)。

這就是為什么 notifyindicate 的區(qū)別不能只停在一句“一個(gè)快一個(gè)穩(wěn)”。

更準(zhǔn)確一點(diǎn)的說(shuō)法應(yīng)該是:

  • notify 面向數(shù)據(jù)流
  • indicate 面向關(guān)鍵狀態(tài)

如果你把這個(gè)邊界想清楚,協(xié)議設(shè)計(jì)會(huì)穩(wěn)很多。

Android 端最容易踩的坑

1. 以為setCharacteristicNotification()就夠了

很多人這樣寫(xiě):

gatt.setCharacteristicNotification(characteristic, true)

然后發(fā)現(xiàn)死活收不到數(shù)據(jù)。

原因通常不是 notify 和 indicate 的區(qū)別,而是你根本沒(méi)寫(xiě) CCCD。

這一步不做,設(shè)備側(cè)很多時(shí)候不會(huì)真正開(kāi)始推送。

2. 寫(xiě)錯(cuò)了 descriptor 值

如果設(shè)備 characteristic 支持的是 indicate,你卻寫(xiě)了 ENABLE_NOTIFICATION_VALUE,那鏈路很可能就不工作。

反過(guò)來(lái)也一樣。

所以這件事不能憑感覺(jué),必須看設(shè)備協(xié)議文檔和 characteristic property。

3. 不看 characteristic 的 property

不是所有 characteristic 都同時(shí)支持 notify 和 indicate。

在 Android 端最好先檢查一下:

val properties = characteristic.properties
val supportsNotify =
    properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0
val supportsIndicate =
    properties and BluetoothGattCharacteristic.PROPERTY_INDICATE != 0

如果設(shè)備只支持其中一種,你寫(xiě)另一種 descriptor 值,本來(lái)就不對(duì)。

4. 以為收不到數(shù)據(jù)一定是 Android 的問(wèn)題

很多時(shí)候 Android 端代碼都寫(xiě)對(duì)了,但還是沒(méi)數(shù)據(jù)。

這時(shí)候問(wèn)題可能在設(shè)備側(cè):

  • 設(shè)備沒(méi)真正開(kāi)啟推送
  • 設(shè)備需要先發(fā)初始化命令
  • 設(shè)備只有在某種模式下才會(huì)上報(bào)
  • 設(shè)備協(xié)議里 notify/indicate 的使用條件有前置狀態(tài)

也就是說(shuō),onCharacteristicChanged() 沒(méi)回調(diào),不等于一定是手機(jī)問(wèn)題。

在協(xié)議設(shè)計(jì)里怎么選

如果你自己能參與設(shè)備協(xié)議設(shè)計(jì),我建議按這個(gè)思路來(lái)分:

高頻、連續(xù)、允許局部丟失的數(shù)據(jù),用 notify
關(guān)鍵、低頻、必須確認(rèn)的狀態(tài),用 indicate

比如:

  • 設(shè)備實(shí)時(shí)傳感器流,優(yōu)先 notify
  • ANC 模式切換結(jié)果,優(yōu)先 indicate
  • 耳機(jī)狀態(tài)周期性同步,優(yōu)先 notify
  • OTA 某一步完成確認(rèn),優(yōu)先 indicate

這樣協(xié)議語(yǔ)義會(huì)更清晰,Android 端也更容易圍繞不同消息建立狀態(tài)機(jī)。

項(xiàng)目里最實(shí)用的一句判斷

如果你現(xiàn)在在做 BLE 項(xiàng)目,遇到“為什么有些消息總感覺(jué)不穩(wěn)”,最先該問(wèn)自己的不是:

“Android 這個(gè)回調(diào)是不是有 bug?”

而是:

“這條消息本來(lái)就應(yīng)該用 notify,還是 indicate?”

因?yàn)楹芏嗍障?wèn)題,根源不是 API 沒(méi)調(diào)對(duì),而是協(xié)議語(yǔ)義一開(kāi)始就選錯(cuò)了。

結(jié)尾

notifyindicate 在 Android 端看起來(lái)很像,都是通過(guò) characteristic 變化把數(shù)據(jù)推上來(lái)。但真正的差異不在回調(diào),而在底層的確認(rèn)語(yǔ)義。

notify 更適合快一點(diǎn)、連續(xù)一點(diǎn)的數(shù)據(jù)。
indicate 更適合慢一點(diǎn)、但必須穩(wěn)一點(diǎn)的關(guān)鍵狀態(tài)。

所以這個(gè)問(wèn)題最后其實(shí)不是“它們有什么區(qū)別”,而是:

你這條消息,到底是在傳數(shù)據(jù)流,還是在傳一個(gè)不能丟的狀態(tài)。

到此這篇關(guān)于A(yíng)ndroid BLE 的 notify 和 indicate 到底有什么區(qū)別的文章就介紹到這了,更多相關(guān)Android BLE notify 和 indicate 區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

玉林市| 泰兴市| 开鲁县| 稷山县| 屯昌县| 新竹市| 如皋市| 象山县| 桃源县| 镇康县| 盈江县| 丰县| 岗巴县| 江源县| 清流县| 定日县| 徐水县| 齐齐哈尔市| 马公市| 翁牛特旗| 临猗县| 翼城县| 娱乐| 新丰县| 电白县| 奇台县| 天等县| 益阳市| 盖州市| 博湖县| 荔浦县| 万荣县| 淳化县| 淳安县| 温宿县| 赤壁市| 黑山县| 嘉黎县| 玉龙| 荥经县| 汾阳市|