BLE核心协议栈全貌:GAP、GATT、ATT、L2CAP、HCI层级拆解
在物联网、智能硬件开发中,BLE(Bluetooth Low Energy,低功耗蓝牙)早已成为设备间近距离通信的核心技术——从智能手环、蓝牙温湿度传感器,到工业设备的数据传输,都离不开BLE协议栈的支撑。很多开发者在开发BLE相关项目时,常常陷入“会调用API,但不懂底层逻辑”的困境:明明能实现设备连接,却搞不清GAP和GATT的区别;能读写特征值,却不知道ATT协议在背后扮演的角色;遇到通信卡顿、连接断开等问题,更是无从排查。
本文将从底层到上层,完整拆解BLE核心协议栈的5个核心层级——HCI、L2CAP、ATT、GATT、GAP,讲清每个层级的定位、核心功能和交互逻辑,同时配套iOS(Swift)、安卓(Kotlin)、Flutter三种主流开发语言的实战代码,让你既能理解底层原理,又能快速落地开发,彻底搞懂BLE协议栈的全貌。
一、BLE协议栈整体架构:从底层到上层的层级划分
BLE协议栈采用分层架构设计,遵循“上层依赖下层、下层为上层提供服务”的原则,从下到上依次为:HCI(主机控制器接口)→ L2CAP(逻辑链路控制和适配协议)→ ATT(属性协议)→ GATT(通用属性配置文件)→ GAP(通用访问配置文件)。
简单来说,底层(HCI、L2CAP)负责“数据传输的通道和规则”,中间层(ATT)负责“数据的定义和编码”,上层(GATT、GAP)负责“设备的交互逻辑和用户可见的行为”。我们可以用一个形象的比喻理解:协议栈就像快递配送系统——GAP是“快递员和收件人”(负责设备发现、连接),GATT是“快递包裹的分类规则”(负责数据的组织和读写),ATT是“包裹上的标签”(定义数据的属性),L2CAP是“快递运输的路线和规则”(负责数据分片和路由),HCI是“快递中转站”(负责主机和控制器的通信)。
接下来,我们逐一拆解每个层级的核心细节,结合实战场景说明其作用,最后给出三种语言的开发示例。
二、分层拆解:每个层级的核心作用与实战意义
第一层:HCI(Host Controller Interface,主机控制器接口)—— 协议栈的“中转站”
HCI是BLE协议栈的最底层(衔接硬件),核心作用是实现主机(Host,如手机)和控制器(Controller,如蓝牙芯片)之间的通信,将上层协议的指令(如“发起连接”“发送数据”)转换为控制器能识别的硬件指令,同时将控制器的状态(如“连接成功”“数据接收”)反馈给上层协议。
通俗来讲,HCI就像主机和控制器之间的“翻译官”:主机(手机App)发出的是“高层指令”(比如“连接设备A”),HCI会将其翻译成控制器(蓝牙芯片)能理解的“底层指令”;反之,控制器检测到设备连接状态变化后,会通过HCI将“底层状态”翻译成“高层反馈”,传递给上层协议(如GAP、GATT)。
核心特点:
-
不直接参与数据的传输和解析,仅负责“指令转换”和“状态反馈”;
-
是硬件和软件的衔接层,不同蓝牙芯片的HCI接口可能不同,但上层协议(GATT、GAP等)完全一致;
-
开发中无需直接操作HCI(系统已封装),但排查连接失败、数据丢失等问题时,需关注HCI日志(如蓝牙芯片是否正常响应指令)。
第二层:L2CAP(Logical Link Control and Adaptation Protocol,逻辑链路控制和适配协议)—— 数据的“运输通道”
L2CAP位于HCI之上,核心作用是为上层协议提供可靠的数据传输通道,主要负责数据的分片、重组和路由,解决“上层数据长度超过蓝牙硬件传输上限”的问题。
BLE硬件的单次数据传输长度有限(默认27字节,BLE 5.0可扩展到251字节),当上层协议(如ATT)发送的数据超过这个上限时,L2CAP会将数据拆分成多个小数据包,传输到对方设备后,再重组为完整数据;同时,L2CAP还会负责数据的路由,确保不同类型的数据(如连接指令、用户数据)能准确传递到对应的上层协议。
核心特点:
-
支持数据分片与重组,突破硬件传输长度限制;
-
提供两种传输模式:面向连接(用于可靠数据传输,如特征值读写)和无连接(用于广播数据,如Beacon广播);
-
开发中无需直接操作L2CAP(系统已封装),但需注意数据长度限制——若读写的数据超过27字节,需开启“长包传输”(BLE 4.2+支持)。
第三层:ATT(Attribute Protocol,属性协议)—— 数据的“标签定义”
ATT位于L2CAP之上,核心作用是定义数据的属性格式和交互规则,是GATT协议的基础。BLE设备之间的数据交互,本质上是“属性的读写操作”,而ATT协议就负责定义这些属性的结构、类型和访问权限。
ATT协议中,每个属性都有三个核心要素:
-
属性句柄(Handle):唯一标识一个属性(类似数组下标),上层协议通过句柄定位属性;
-
属性类型(UUID):定义属性的用途(如“温度数据”“设备名称”),常用的UUID有固定规范(如设备名称UUID为0x2A00);
-
属性值(Value):实际存储的数据(如温度值25℃、设备名称“Smart Sensor”);
-
访问权限(Permissions):定义属性的操作权限(如只读、可写、可通知)。
核心特点:
-
ATT协议的交互逻辑非常简单:只有“读属性”“写属性”两种核心操作;
-
所有GATT服务、特征值,本质上都是ATT属性的组合;
-
开发中,我们操作GATT特征值时,底层其实是通过ATT协议的“读句柄”“写句柄”实现的。
第四层:GATT(Generic Attribute Profile,通用属性配置文件)—— 数据的“组织规则”
GATT位于ATT之上,核心作用是将ATT属性组织成“服务(Service)”和“特征值(Characteristic)”的结构,让数据的交互更具逻辑性,方便开发者理解和使用。
我们可以把GATT的结构理解为“文件夹-文件”的结构:
-
服务(Service):一组相关属性的集合(类似文件夹),每个服务有一个唯一的UUID(如“温湿度监测服务”UUID为0x180A);
-
特征值(Characteristic):服务下的具体数据项(类似文件),每个特征值对应一个ATT属性,包含“特征值UUID”“特征值数据”“访问权限”;
-
描述符(Descriptor):用于补充特征值的信息(如特征值的单位、范围),也是一种ATT属性(如“温度单位描述符”)。
核心特点:
-
GATT是BLE数据交互的核心,几乎所有BLE设备的通信都基于GATT协议;
-
设备连接后,需先发现对方的GATT服务和特征值,才能进行数据读写、通知等操作;
-
开发中,我们最常操作的就是GATT服务和特征值(如读取温湿度特征值、写入控制指令)。
第五层:GAP(Generic Access Profile,通用访问配置文件)—— 设备的“交互入口”
GAP是BLE协议栈的最上层,核心作用是定义设备的对外交互行为,负责设备的发现、连接、配对、广播等用户可见的操作,是设备之间建立通信的“入口”。
GAP协议将BLE设备分为两种角色:
-
广播者(Advertiser):主动发送广播数据(如设备名称、UUID、信号强度),让其他设备发现自己(如智能传感器、手环);
-
扫描者(Scanner):主动扫描周围的广播设备,发起连接请求(如手机、平板)。
核心功能:
-
广播与扫描:广播者发送广播包,扫描者扫描广播包,获取设备基本信息;
-
连接管理:扫描者发起连接,广播者接受连接,建立BLE连接;
-
配对与加密:为了保证数据安全,连接后可进行配对(如输入PIN码),对数据进行加密传输;
-
设备信息展示:定义设备名称、外观、角色等信息,供扫描者识别。
核心特点:
-
GAP是设备之间建立通信的第一步,没有GAP的广播和扫描,就无法建立GATT连接;
-
开发中,我们首先要实现的就是GAP相关操作(扫描设备、发起连接),再进行GATT数据交互。
三、三种语言实战:GAP/GATT核心操作代码(落地可用)
理解了各层级的核心作用后,我们结合实战场景,给出iOS(Swift)、安卓(Kotlin)、Flutter三种语言的核心代码——实现“扫描BLE设备→发起连接→发现GATT服务和特征值→读写特征值”的完整流程,覆盖GAP和GATT的核心操作(底层HCI、L2CAP、ATT由系统封装,无需手动操作)。
1. iOS(Swift)实战代码(基于CoreBluetooth框架)
iOS中使用CoreBluetooth框架操作BLE,核心是CBPeripheralManager(广播者)和CBCentralManager(扫描者),以下是扫描、连接、读写特征值的完整代码:
import CoreBluetooth
// 扫描者(手机端):负责扫描设备、发起连接、读写特征值
class BLECentralManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
private var centralManager: CBCentralManager!
private var targetPeripheral: CBPeripheral? // 目标设备
// 目标服务和特征值UUID(根据实际设备修改)
private let targetServiceUUID = CBUUID(string: "0000180A-0000-1000-8000-00805F9B34FB") // 设备信息服务
private let targetCharUUID = CBUUID(string: "00002A00-0000-1000-8000-00805F9B34FB") // 设备名称特征值
override init() {
super.init()
// 初始化中心管理器(GAP扫描的核心)
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
// 中心管理器状态变化(检查蓝牙是否可用)
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
print("蓝牙已开启,开始扫描设备(GAP扫描)")
// 开始扫描GAP广播的设备,过滤目标服务UUID
central.scanForPeripherals(withServices: [targetServiceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
case .poweredOff:
print("蓝牙已关闭")
default:
print("蓝牙状态异常:\(central.state)")
}
}
// 发现BLE设备(GAP广播被扫描到)
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("发现设备:\(peripheral.name ?? "未知设备"),RSSI:\(RSSI)")
// 过滤目标设备(可根据设备名称、UUID过滤)
if peripheral.name == "Smart Sensor" {
targetPeripheral = peripheral
// 停止扫描,发起连接(GAP连接)
central.stopScan()
central.connect(peripheral, options: nil)
}
}
// 连接设备成功
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("设备连接成功,开始发现GATT服务")
// 设置外设代理,用于发现GATT服务和特征值
peripheral.delegate = self
// 发现设备的GATT服务(ATT属性的组织)
peripheral.discoverServices([targetServiceUUID])
}
// 发现GATT服务
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print("发现GATT服务:\(service.uuid)")
// 发现服务下的GATT特征值
peripheral.discoverCharacteristics([targetCharUUID], for: service)
}
}
// 发现GATT特征值
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let characteristics = service.characteristics else { return }
for char in characteristics {
print("发现GATT特征值:\(char.uuid),权限:\(char.properties)")
// 读取特征值(底层通过ATT协议读属性)
if char.uuid == targetCharUUID {
peripheral.readValue(for: char)
// 若特征值支持通知,开启通知(实时接收数据)
if char.properties.contains(.notify) {
peripheral.setNotifyValue(true, for: char)
}
}
}
}
// 读取特征值成功(获取ATT属性值)
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
guard let data = characteristic.value, let value = String(data: data, encoding: .utf8) else { return }
print("读取特征值成功:\(value)")
}
// 写入特征值(底层通过ATT协议写属性)
func writeValue(to peripheral: CBPeripheral, characteristic: CBCharacteristic, value: String) {
guard let data = value.data(using: .utf8) else { return }
// 写入特征值(withResponse:是否需要响应,确保写入成功)
peripheral.writeValue(data, for: characteristic, type: .withResponse)
}
// 断开连接
func disconnectPeripheral() {
guard let peripheral = targetPeripheral else { return }
centralManager.cancelPeripheralConnection(peripheral)
}
}
// 使用示例
let bleManager = BLECentralManager()
2. 安卓(Kotlin)实战代码(基于BluetoothGatt框架)
安卓中使用BluetoothGatt框架操作BLE,核心是BluetoothAdapter(蓝牙适配器)、BluetoothDevice(蓝牙设备)、BluetoothGatt(GATT连接),以下是完整代码(需在AndroidManifest中添加蓝牙权限):
import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothProfile
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
class BLEActivity : AppCompatActivity() {
private lateinit var bluetoothAdapter: BluetoothAdapter
private var bluetoothGatt: BluetoothGatt? = null
// 目标服务和特征值UUID(根据实际设备修改)
private val targetServiceUUID = "0000180A-0000-1000-8000-00805F9B34FB" // 设备信息服务
private val targetCharUUID = "00002A00-0000-1000-8000-00805F9B34FB" // 设备名称特征值
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ble)
// 初始化蓝牙适配器(GAP扫描的核心)
val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
bluetoothAdapter = bluetoothManager.adapter
// 检查蓝牙是否可用
if (!bluetoothAdapter.isEnabled) {
bluetoothAdapter.enable() // 开启蓝牙
Toast.makeText(this, "正在开启蓝牙...", Toast.LENGTH_SHORT).show()
}
// 检查权限(安卓12+需额外申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT),
1001
)
return
}
}
// 开始扫描GAP广播的设备
startScan()
}
// 开始扫描BLE设备(GAP扫描)
private fun startScan() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED
) {
return
}
// 扫描回调,获取GAP广播的设备信息
bluetoothAdapter.startLeScan { device, rssi, scanRecord ->
device?.let {
// 过滤目标设备(根据设备名称、UUID过滤)
if (it.name == "Smart Sensor") {
Toast.makeText(this, "发现设备:${it.name}", Toast.LENGTH_SHORT).show()
// 停止扫描,发起GAP连接
bluetoothAdapter.stopLeScan()
connectDevice(it)
}
}
}
}
// 连接BLE设备(GAP连接)
private fun connectDevice(device: BluetoothDevice) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
return
}
// 建立GATT连接,获取GATT客户端
bluetoothGatt = device.connectGatt(this, false, gattCallback)
}
// GATT回调(处理GATT连接、服务发现、特征值读写)
private val gattCallback = object : BluetoothGattCallback() {
// GATT连接状态变化
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
when (newState) {
BluetoothProfile.STATE_CONNECTED -> {
Toast.makeText(this@BLEActivity, "设备连接成功", Toast.LENGTH_SHORT).show()
// 发现GATT服务(ATT属性的组织)
gatt?.discoverServices()
}
BluetoothProfile.STATE_DISCONNECTED -> {
Toast.makeText(this@BLEActivity, "设备断开连接", Toast.LENGTH_SHORT).show()
}
}
}
// 发现GATT服务
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
if (status != BluetoothGatt.GATT_SUCCESS) return
// 获取所有GATT服务
gatt?.services?.forEach { service ->
if (service.uuid.toString() == targetServiceUUID) {
Toast.makeText(this@BLEActivity, "发现目标服务:${service.uuid}", Toast.LENGTH_SHORT).show()
// 发现服务下的GATT特征值
service.characteristics.forEach { char ->
if (char.uuid.toString() == targetCharUUID) {
// 读取特征值(底层通过ATT协议读属性)
gatt.readCharacteristic(char)
// 开启特征值通知(实时接收数据)
if (char.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0) {
gatt.setCharacteristicNotification(char, true)
}
}
}
}
}
}
// 读取特征值成功(获取ATT属性值)
override fun onCharacteristicRead(
gatt: BluetoothGatt?,
characteristic: BluetoothGattCharacteristic?,
status: Int
) {
super.onCharacteristicRead(gatt, characteristic, status)
if (status == BluetoothGatt.GATT_SUCCESS) {
characteristic?.value?.let { data ->
val value = String(data, Charsets.UTF_8)
Toast.makeText(this@BLEActivity, "读取特征值:$value", Toast.LENGTH_SHORT).show()
}
}
}
// 写入特征值成功
override fun onCharacteristicWrite(
gatt: BluetoothGatt?,
characteristic: BluetoothGattCharacteristic?,
status: Int
) {
super.onCharacteristicWrite(gatt, characteristic, status)
if (status == BluetoothGatt.GATT_SUCCESS) {
Toast.makeText(this@BLEActivity, "写入特征值成功", Toast.LENGTH_SHORT).show()
}
}
}
// 写入特征值(底层通过ATT协议写属性)
fun writeCharacteristic(value: String) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
return
}
bluetoothGatt?.services?.forEach { service ->
if (service.uuid.toString() == targetServiceUUID) {
service.characteristics.forEach { char ->
if (char.uuid.toString() == targetCharUUID) {
char.value = value.toByteArray(Charsets.UTF_8)
bluetoothGatt?.writeCharacteristic(char)
}
}
}
}
}
// 断开连接
override fun onDestroy() {
super.onDestroy()
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
return
}
bluetoothGatt?.disconnect()
bluetoothGatt?.close()
}
}
注意:安卓端需在AndroidManifest.xml中添加以下权限(根据系统版本适配):
<!-- 蓝牙基础权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!-- 安卓12+权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 蓝牙低功耗权限 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
3. Flutter实战代码(基于flutter_blue_plus插件)
Flutter中操作BLE需依赖第三方插件(推荐flutter_blue_plus,兼容iOS和安卓),以下是完整代码,实现跨平台的BLE扫描、连接、读写特征值:
第一步:添加依赖(pubspec.yaml)
dependencies:
flutter:
sdk: flutter
flutter_blue_plus: ^1.13.3 # 最新版本可在pub.dev查询
第二步:平台配置(iOS/安卓)
-
iOS:在Info.plist中添加蓝牙权限 NSBluetoothAlwaysUsageDescription(蓝牙使用说明) NSBluetoothPeripheralUsageDescription(兼容旧版本)
-
安卓:在AndroidManifest.xml中添加上述安卓权限
第三步:核心代码
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
class BLEPage extends StatefulWidget {
const BLEPage({super.key});
@override
State<BLEPage> createState() => _BLEPageState();
}
class _BLEPageState extends State<BLEPage> {
FlutterBluePlus flutterBlue = FlutterBluePlus.instance;
BluetoothDevice? targetDevice; // 目标设备
BluetoothCharacteristic? targetChar; // 目标特征值
// 目标服务和特征值UUID(根据实际设备修改)
final Guid targetServiceGuid = Guid("0000180A-0000-1000-8000-00805F9B34FB"); // 设备信息服务
final Guid targetCharGuid = Guid("00002A00-0000-1000-8000-00805F9B34FB"); // 设备名称特征值
@override
void initState() {
super.initState();
// 初始化蓝牙,监听蓝牙状态
initBLE();
}
// 初始化BLE,检查蓝牙状态
void initBLE() {
// 监听蓝牙状态变化
flutterBlue.state.listen((BluetoothState state) {
switch (state) {
case BluetoothState.on:
print("蓝牙已开启,开始扫描设备(GAP扫描)");
startScan(); // 开启扫描
break;
case BluetoothState.off:
print("蓝牙已关闭,请开启蓝牙");
break;
default:
break;
}
});
}
// 开始扫描GAP广播的设备
void startScan() {
// 停止之前的扫描(避免重复扫描)
flutterBlue.stopScan();
// 开始扫描,过滤目标服务UUID,扫描时长4秒
flutterBlue.startScan(
withServices: [targetServiceGuid],
timeout: const Duration(seconds: 4),
);
// 监听扫描结果(GAP广播数据)
flutterBlue.scanResults.listen((List<ScanResult> results) {
for (ScanResult result in results) {
// 过滤目标设备(根据设备名称过滤)
if (result.device.name == "Smart Sensor") {
setState(() {
targetDevice = result.device;
});
print("发现设备:${result.device.name},RSSI:${result.rssi}");
// 停止扫描,发起GAP连接
flutterBlue.stopScan();
connectDevice();
}
}
});
}
// 连接BLE设备(GAP连接)
void connectDevice() async {
if (targetDevice == null) return;
try {
// 发起连接
await targetDevice!.connect();
print("设备连接成功,开始发现GATT服务");
// 发现GATT服务(ATT属性的组织)
discoverServices();
} catch (e) {
print("连接失败:$e");
}
}
// 发现GATT服务和特征值
void discoverServices() async {
if (targetDevice == null) return;
// 获取设备的所有GATT服务
List<BluetoothService> services = await targetDevice!.discoverServices();
for (BluetoothService service in services) {
if (service.uuid == targetServiceGuid) {
print("发现目标服务:${service.uuid}");
// 获取服务下的所有GATT特征值
for (BluetoothCharacteristic char in service.characteristics) {
if (char.uuid == targetCharGuid) {
setState(() {
targetChar = char;
});
print("发现目标特征值:${char.uuid}");
// 读取特征值(底层通过ATT协议读属性)
readCharacteristic();
// 开启特征值通知(实时接收数据)
if (char.properties.contains(BluetoothCharacteristicProperty.notify)) {
await char.setNotifyValue(true);
// 监听特征值变化
char.value.listen((value) {
String data = String.fromCharCodes(value);
print("实时接收特征值:$data");
});
}
}
}
}
}
}
// 读取特征值
void readCharacteristic() async {
if (targetChar == null) return;
try {
// 读取特征值(底层通过ATT协议读属性)
await targetChar!.read();
String value = String.fromCharCodes(targetChar!.value);
print("读取特征值成功:$value");
} catch (e) {
print("读取特征值失败:$e");
}
}
// 写入特征值(底层通过ATT协议写属性)
void writeCharacteristic(String value) async {
if (targetChar == null) return;
try {
// 写入特征值
await targetChar!.write(utf8.encode(value), withoutResponse: false);
print("写入特征值成功:$value");
} catch (e) {
print("写入特征值失败:$e");
}
}
// 断开连接
void disconnectDevice() async {
if (targetDevice == null) return;
await targetDevice!.disconnect();
print("设备断开连接");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("BLE实战")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(targetDevice?.name ?? "未发现设备"),
const SizedBox(height: 20),
ElevatedButton(
onPressed: startScan,
child: const Text("扫描设备"),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: targetDevice != null ? disconnectDevice : null,
child: const Text("断开连接"),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: targetChar != null ? () => writeCharacteristic("测试写入") : null,
child: const Text("写入特征值"),
),
],
),
),
);
}
@override
void dispose() {
// 页面销毁时断开连接
disconnectDevice();
super.dispose();
}
}
四、核心总结:层级关系与开发注意事项
1. 层级关系梳理(必记)
从底层到上层:HCI(硬件衔接)→ L2CAP(数据运输)→ ATT(属性定义)→ GATT(数据组织)→ GAP(设备交互),每层的核心作用可总结为:
-
HCI:翻译指令,衔接硬件与软件;
-
L2CAP:分片重组,保障数据传输;
-
ATT:定义属性,规范数据格式;
-
GATT:组织数据,提供交互接口;
-
GAP:管理连接,实现设备发现。
2. 开发注意事项(避坑重点)
-
权限适配:iOS需在Info.plist添加蓝牙权限说明,安卓需根据系统版本申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT等权限,否则会导致扫描失败、连接失败;
-
数据长度限制:BLE默认单次传输27字节,若需传输更长数据,需开启长包传输(BLE 4.2+),否则会导致数据丢失;
-
连接稳定性:BLE连接容易受距离、干扰影响,需添加重连机制(如断开连接后自动扫描重连);
-
UUID规范:GATT服务和特征值的UUID需与硬件设备一致,否则无法发现服务、读写特征值;
-
资源释放:开发中需及时断开GATT连接、停止扫描,避免内存泄漏(尤其是Flutter跨平台开发,需注意原生资源的释放)。
更多推荐

所有评论(0)