Android BLE 连接 SDK
SDK Version: 1.0.0
Package:com.xtalk.mesh.sdk.ble
初始化
在 Application 或首次进入 BLE 功能前设置应用 Context 并初始化。ensureInitialized() 可重复调用。
XTalkBleClient.setApplicationContext(applicationContext)
val initResult = XTalkBleClient.ensureInitialized()
请检查 initResult 是否为 InitResult.INIT_OK 或交付核心 SDK 定义的“已经初始化”成功状态。
扫描
先注册 DeviceStateCallback,再开始扫描:
private val deviceCallback = DeviceStateCallback { state, devices, _, _ ->
if (state == DeviceEventState.SCAN_RESULT) {
val supported = devices.orEmpty().filter(::isSupportedBleDevice)
// 在 UI 层展示 supported;不要在回调中阻塞。
}
}
XTalkBleClient.addListener(deviceCallback)
val scanResult = XTalkBleClient.startScan(
timeoutMs = 8_000,
minRssiDbm = -100,
serviceUuids = listOf(XTALK_SCAN_UUID_5632G),
)
页面离开、开始连接或用户取消时调用 stopScan()。设备名称显示可使用 bleDeviceDisplayName(device)。
连接与就绪
connect、awaitBleReady、认证和初始化会等待设备响应,不要在主线程调用:
val connectResult = withContext(Dispatchers.IO) {
XTalkBleClient.connect(
device = device,
timeoutMs = 8_000,
maxReconnectAttempts = null,
)
}
if (connectResult == ConnectResult.CONNECT_OK) {
val gattReady = withContext(Dispatchers.IO) {
XTalkBleClient.awaitBleReady(timeoutMs = 8_000L)
}
}
CONNECT_OK 只表示连接请求成功;后续请等待状态回调和 GATT 就绪,然后执行认证。isReadyForSend() 只有在连接并完成无线初始化后才返回 true。
AT 与业务数据
val lines = withContext(Dispatchers.IO) {
XTalkBleClient.runAtCommand("AT+VER?", timeoutMs = 3_000L, log = true)
}
val sendResult = withContext(Dispatchers.IO) {
XTalkBleClient.sendBinaryFrame(payload)
}
不要在认证、初始化、OTA 或其他独占 AT 操作期间并发发送 AT 命令。普通业务发送前检查 isReadyForSend()。
断开与清理
withContext(Dispatchers.IO) {
XTalkBleClient.disconnect(sendRemoteCommand = true)
}
XTalkBleClient.removeListener(deviceCallback)
异常恢复时可使用 sendRemoteCommand = false。所有通过 add...Listener 注册的回调,都必须由同一生命周期所有者调用相应的 remove...Listener。
连接生命周期 API 完整契约
| API | 默认/前置 | 返回、超时和清理 |
|---|---|---|
setApplicationContext(context) | Application Context;初始化前 | null 清除;不持有 Activity |
ensureInitialized() | 无;可重复调用 | InitResult.INIT_OK 才继续;注册核心回调失败返回 Init 失败 |
startScan(timeoutMs=5000, minRssiDbm=-100, serviceUuids=[]) | 权限和蓝牙开启 | ScanStartResult;结果通过 DeviceStateCallback;与 stopScan() 配对 |
stopScan() | 已初始化 | 幂等停止;无返回 |
connect(device, timeoutMs=5000, maxReconnectAttempts=null) | 先停止扫描;后台线程 | ConnectResult 是请求结果;再用 callback/awaitConnected 确认 |
awaitConnected(macAddress=null, timeoutMs=8000) | 后台线程 | 匹配设备 CONNECTED 为 true;ERROR/DISCONNECTED/超时为 false;内部 waiter 自动移除 |
ensureGattServicesOpened(forceReset=false) | 已 CONNECTED;后台线程 | 重新打开透传/协议服务;会短暂阻塞;无返回 |
awaitBleReady(timeoutMs=8000) | CONNECTED;后台线程 | GATT 写入和通知稳定为 true;断线/期限为 false |
disconnect(sendRemoteCommand=true) | 后台线程 | DisconnectResult;清缓存/ready/AT 模式;异常链路可传 false |
awaitDisconnected(timeoutMs=6000) | 后台线程 | DISCONNECTED 为 true;ERROR/期限为 false |
stopAutoReconnect(reason) | 需要结束 SDK 重连时 | 找到并停止 manager 为 true;不替代 disconnect |
forceResetDisconnected(reason, clearLastRequestedDevice=true) | 仅状态与底层连接不一致的恢复路径 | 清本地追踪/ready/AT;正常断开优先 disconnect |
状态与 Auth/Init 门槛
| API | 含义 |
|---|---|
getConnectedDevice() | 当前合并后的设备或 null |
getConnectionState() | 当前 DeviceEventState |
hasActiveBleLink() | 设备非空且状态为 CONNECTED |
getDeviceLongId() / awaitDeviceLongId(timeoutMs=3000) | 已认证结构化 DID;后者阻塞轮询,断线/超时为 null |
isWirelessReady() / awaitWirelessReady(timeoutMs=4000) | Init ready 状态;后者等待配置 callback |
isReadyForSend() | CONNECTED 且 wireless ready;业务发送唯一总门槛 |
markWirelessInitRequired(reason, resetAtMode=true) | 设备状态失效时清 ready;通常由 Auth 调用 |
setWirelessInitReady(ready, reason) | Auth/Init 集成用状态写入;客户业务不要伪造 true |
AT 编码选择(Advanced)
isAtXorEnabled()读取当前连接 AT 编码状态。setAtXorEnabledForConnection(enabled, reason)只供 Auth/兼容适配器切换当前连接;连接/断开会重置。chooseAtXorModeByFreqProbeResult(timeoutMs=1500, log=true)依次探测普通/XOR,返回AtXorModeProbeResult(useXor, normalFreqAccepted)或null。- 客户应用应优先调用
DeviceAuthenticator,不要自行猜测编码或跳过 Challenge。
名称与权限辅助
requiredBluetoothPermissions、requiredStartupPermissions、hasBluetoothPermissions、hasStartupPermissions 见环境设置。sanitizeBleDeviceName 清空占位符、短数字/十六进制和 DID 样式名称;isSupportedBleDeviceName/isSupportedBleDevice 只接受 xTalk 支持关键字/前缀;bleDeviceDisplayName 无合法名称时回退大写 MAC;mergeBleDeviceIdentity(reported, fallback) 按 MAC、合法名称和 RSSI 合并,二者都无 MAC 时为 null。
所有 addListener 及业务 add...Listener 都以集合保存同一实例;重复添加同一实例不会产生额外集合项,但仍应严格一进一出。完整配对表见数据与设备能力。