HarmonyOS鸿蒙Next中蓝牙设备可配对成功但是连接却是一直失败,代码写在下面了,就是在连接到时候出现问题,连接不上,希望有大佬解决
HarmonyOS鸿蒙Next中蓝牙设备可配对成功但是连接却是一直失败,代码写在下面了,就是在连接到时候出现问题,连接不上,希望有大佬解决
import { access } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
//适配器管理器
export class AdapterManager {
// 定义蓝牙开关状态变化函数回调
onReceiveEvent = (data: access.BluetoothState) => {
let btStateMessage = '';
switch (data) {
case access.BluetoothState.STATE_OFF:
// 表示蓝牙是关闭的
btStateMessage += 'STATE_OFF';
break;
case access.BluetoothState.STATE_TURNING_ON:
btStateMessage += 'STATE_TURNING_ON';
break;
case access.BluetoothState.STATE_ON:
// 表示蓝牙是开启的,此时应用才可以使用蓝牙其他功能
btStateMessage += 'STATE_ON';
break;
case access.BluetoothState.STATE_TURNING_OFF:
btStateMessage += 'STATE_TURNING_OFF';
break;
case access.BluetoothState.STATE_BLE_TURNING_ON:
btStateMessage += 'STATE_BLE_TURNING_ON';
break;
case access.BluetoothState.STATE_BLE_ON:
btStateMessage += 'STATE_BLE_ON';
break;
case access.BluetoothState.STATE_BLE_TURNING_OFF:
btStateMessage += 'STATE_BLE_TURNING_OFF';
break;
default:
btStateMessage += 'unknown state';
break;
}
console.info('bluetooth state: ' + btStateMessage);
};
// 开启蓝牙
public openBluetooth() {
try {
access.on('stateChange', this.onReceiveEvent);
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
try {
// 主动获取蓝牙当前的开关状态
let state = access.getState();
if (state == access.BluetoothState.STATE_OFF) {
// 若蓝牙是关闭的,则主动开启蓝牙
access.enableBluetooth();
}
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
// 关闭蓝牙
public closeBluetooth() {
try {
// 主动获取蓝牙当前的开关状态
let state = access.getState();
if (state == access.BluetoothState.STATE_ON) {
// 若蓝牙是开启的,则主动关闭蓝牙
access.disableBluetooth();
}
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
}
let adapterManager = new AdapterManager();
export default adapterManager as AdapterManager;
import { connection } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
//发现设备管理器
export class DiscoveryDeviceManager {
// 定义扫描结果上报回调函数
onReceiveEvent = (data: Array<string>) => {
console.info('bluetooth device: ' + JSON.stringify(data));
};
public startDiscovery() {
try {
connection.on('bluetoothDeviceFind', this.onReceiveEvent);
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
try {
// 判断本机设备是否正在进行扫描
let scan = connection.isBluetoothDiscovering();
if (!scan) {
// 若当前不处于扫描过程,则开始扫描设备
connection.startBluetoothDiscovery();
}
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
public stopDiscovery() {
try {
// 判断本机设备是否正在进行扫描
let scan = connection.isBluetoothDiscovering();
if (scan) {
// 若当前处于扫描过程,则停止扫描设备
connection.stopBluetoothDiscovery();
}
// 若不再需要使用扫描,可以取消订阅扫描上报结果
connection.off('bluetoothDeviceFind', this.onReceiveEvent);
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
public setScanMode() {
try {
// 获取当前本机的扫描模式
let scanMode: connection.ScanMode = connection.getBluetoothScanMode();
console.info('scanMode: ' + scanMode);
if (scanMode != connection.ScanMode.SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE) {
// 将本机设备的扫描模式设为可被发现和可被连接
connection.setBluetoothScanMode(connection.ScanMode.SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE, 0);
}
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
public getPairedDevices() {
try {
// 获取已配对设备信息
let devices = connection.getPairedDevices();
console.info('pairedDevices: ' + JSON.stringify(devices));
// 若已知道设备地址,可主动查询该设备是否是已配对的
if (devices.length > 0) {
let pairState = connection.getPairState(devices[0]);
console.info('device: ' + devices[0] + ' pairState is ' + pairState);
}
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
}
let discoveryDeviceManager = new DiscoveryDeviceManager();
export default discoveryDeviceManager as DiscoveryDeviceManager;
import { connection, a2dp, hfp, hid, baseProfile, constant } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
//配对设备管理器
export class PairDeviceManager {
device: string = '';
pairState: connection.BondState = connection.BondState.BOND_STATE_INVALID;
a2dpSrc = a2dp.createA2dpSrcProfile();
hfpAg = hfp.createHfpAgProfile();
hidHost = hid.createHidHostProfile();
// 定义配对状态变化回调函数
onBondStateEvent = (data: connection.BondStateParam) => {
console.info('pair result: ' + JSON.stringify(data));
if (data && data.deviceId == this.device) {
this.pairState = data.state; // 保存目标设备的配对状态
}
};
// 发起配对,设备地址可以通过查找设备流程获取
public startPair(device: string) {
this.device = device;
try {
// 发起订阅配对状态变化事件
connection.on('bondStateChange', this.onBondStateEvent);
} catch (err) {
console.error('bondStateChange errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
try {
// 发起配对
connection.pairDevice(device).then(() => {
console.info('pairDevice');
}, (error: BusinessError) => {
console.error('pairDevice: errCode:' + error.code + ',errMessage' + error.message);
});
} catch (err) {
console.error('startPair: errCode:' + err.code + ',errMessage' + err.message);
}
}
// 定义A2DP连接状态变化回调函数
onA2dpConnectStateChange = (data: baseProfile.StateChangeParam) => {
console.info(`A2DP State: ${JSON.stringify(data)}`);
};
// 定义HFP连接状态变化回调函数
onHfpConnectStateChange = (data: baseProfile.StateChangeParam) => {
console.info(`HFP State: ${JSON.stringify(data)}`);
};
// 定义HID连接状态变化回调函数
onHidConnectStateChange = (data: baseProfile.StateChangeParam) => {
console.info(`HID State: ${JSON.stringify(data)}`);
};
// 发起连接
public async connect(device: string) {
try {
let uuids = await connection.getRemoteProfileUuids(device);
console.info('device: ' + device + ' remoteUuids: ' + JSON.stringify(uuids));
let allowedProfiles = 0;
// 若存在应用需要的profile,则监听对应的profile连接状态
if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_A2DP_SINK.toLowerCase())) {
console.info('device supports a2dp');
allowedProfiles++;
this.a2dpSrc.on('connectionStateChange', this.onA2dpConnectStateChange);
}
if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HFP_HF.toLowerCase())) {
console.info('device supports hfp');
allowedProfiles++;
this.hfpAg.on('connectionStateChange', this.onHfpConnectStateChange);
}
if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HID.toLowerCase()) ||
uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HOGP.toLowerCase())) {
console.info('device supports hid');
allowedProfiles++;
this.hidHost.on('connectionStateChange', this.onHidConnectStateChange);
}
if (allowedProfiles > 0) { // 若存在可用的profile,则发起连接
connection.connectAllowedProfiles(device).then(() => {
console.info('connectAllowedProfiles');
}, (error: BusinessError) => {
console.error('errCode:' + error.code + ',errMessage' + error.message);
});
}
} catch (err) {
console.error('errCode:' + err.code + ',errMessage' + err.message);
}
}
}
let pairDeviceManager = new PairDeviceManager();
export default pairDeviceManager as PairDeviceManager;
import { socket } from '@kit.ConnectivityKit'
import { BusinessError } from '@kit.BasicServicesKit';
class SppClientManager {
// 定义客户端的socket id
clientNumber: number = -1;
// 发起连接
public startConnect(peerDevice: string): void {
// 配置连接参数
let option: socket.SppOptions = {
uuid: '00009999-0000-1000-8000-00805F9B34FB', // 需要连接的服务端UUID服务,确保服务端支持
secure: false,
type: socket.SppType.SPP_RFCOMM
};
console.info('startConnect ' + peerDevice);
socket.sppConnect(peerDevice, option, (err, num: number) => {
if (err) {
console.error('startConnect errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
} else {
console.info('startConnect clientNumber: ' + num);
this.clientNumber = num;
}
});
console.info('startConnect after ' + peerDevice);
}
// 发送数据
public sendData(data: ArrayBuffer) {
console.info('sendData ' + this.clientNumber + ', data length: ' + data.byteLength);
try {
socket.sppWrite(this.clientNumber, data); // 使用传入的 data
} catch (err) {
console.error('发送失败: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
// 定义接收数据的回调函数
read = (dataBuffer: ArrayBuffer) => {
let data = new Uint8Array(dataBuffer);
console.info('client data: ' + JSON.stringify(data));
};
// 接收数据
public readData() {
try {
// 发起订阅
socket.on('sppRead', this.clientNumber, this.read);
} catch (err) {
console.error('readData errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
// 断开连接
public stopConnect() {
console.info('closeSppClient ' + this.clientNumber);
try {
// 取消接收数据订阅
socket.off('sppRead', this.clientNumber, this.read);
} catch (err) {
console.error('off sppRead errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
try {
// 从client端断开连接
socket.sppCloseClientSocket(this.clientNumber);
} catch (err) {
console.error('stopConnect errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
}
let sppClientManager = new SppClientManager();
export default sppClientManager as SppClientManager;
import { socket } from '@kit.ConnectivityKit'
import { BusinessError } from '@kit.BasicServicesKit';
class SppServerManager {
serverNumber: number = -1;
clientNumber: number = -1;
// 创建服务端监听socket
public startListen(): void {
console.info('startListen');
// 配置监听参数
let option: socket.SppOptions = {
uuid: '00009999-0000-1000-8000-00805F9B34FB',
secure: false,
type: socket.SppType.SPP_RFCOMM
};
// 创建服务端监听socket,将在蓝牙子系统中注册该UUID服务
socket.sppListen("demonstration", option, (err, num: number) => {
if (err) {
console.error('sppListen errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
} else {
console.info('sppListen serverNumber: ' + num);
this.serverNumber = num;
}
});
}
// 监听连接请求,等待连接
public accept() {
console.info('accept ' + this.serverNumber);
if (this.serverNumber == -1) {
console.error('invalid serverNumber');
return;
}
socket.sppAccept(this.serverNumber, (err, num: number) => {
if (err) {
console.error('accept errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
} else {
console.info('accept clientNumber: ' + num);
this.clientNumber = num;
}
});
}
// 发送数据
public sendData() {
console.info('sendData serverNumber: ' + this.serverNumber + ' clientNumber: ' + this.clientNumber);
if (this.clientNumber == -1) {
console.error('invalid clientNumber');
return;
}
let arrayBuffer = new ArrayBuffer(2);
let data = new Uint8Array(arrayBuffer);
data[0] = 9;
data[1] = 8;
try {
socket.sppWrite(this.clientNumber, arrayBuffer);
} catch (err) {
console.error('sppWrite errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
// 定义接收数据的回调函数
read = (dataBuffer: ArrayBuffer) => {
let data = new Uint8Array(dataBuffer);
console.info('client data: ' + JSON.stringify(data));
};
// 接收数据
public readData() {
try {
// 发起订阅
if (this.clientNumber == -1) {
console.error('invalid clientNumber');
return;
}
socket.on('sppRead', this.clientNumber, this.read);
} catch (err) {
console.error('readData errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
// 停止连接
public stopConnect() {
console.info('stopConnect');
try {
// 取消订阅
if (this.clientNumber == -1) {
console.error('invalid clientNumber');
return;
}
socket.off('sppRead', this.clientNumber, this.read);
} catch (err) {
console.error('off sppRead errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
try {
// 从server断开连接
socket.sppCloseClientSocket(this.clientNumber);
} catch (err) {
console.error('stopConnect errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
// 删除能力
public closeSppServer() {
console.info('closeSppServer');
try {
// 若应用不再需要此能力,则主动删除
if (this.serverNumber == -1) {
console.error('invalid serverNumber');
return;
}
socket.sppCloseServerSocket(this.serverNumber);
} catch (err) {
console.error('sppCloseServerSocket errCode: ' + (err as BusinessError).code + ', errMessage: ' +
(err as BusinessError).message);
}
}
}
let sppServerManager = new SppServerManager();
export default sppServerManager as SppServerManager;
import adapterManager from '../manager/AdapterManager';
import discoveryDeviceManager from '../manager/DiscoveryDeviceManager';
import pairDeviceManager from '../manager
更多关于HarmonyOS鸿蒙Next中蓝牙设备可配对成功但是连接却是一直失败,代码写在下面了,就是在连接到时候出现问题,连接不上,希望有大佬解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html
【背景知识】
蓝牙socket:提供了操作和管理蓝牙socket的方法。
【参考方案】 可参考蓝牙通信示例,通过@ohos.bluetooth.socket实现蓝牙通信,完成设备之间的信息发送效果。
- sppConnect():调用socket.sppConnect方法,尝试与指定MAC地址的蓝牙设备建立SPP连接。
sppConnect() {
······
let sppOption: socket.SppOptions = { uuid: Constants.UUID, secure: false, type: 0 };
try {
socket.sppConnect(this.mac, sppOption, clientSocket);
}
······
}
- sppListen():调用socket.sppListen方法,在蓝牙设备上启动SPP服务,等待其他设备连接。
sppListen() {
let sppOption: socket.SppOptions = { uuid: Constants.UUID, secure: false, type: 0 };
try {
socket.sppListen('BT_SOCKET', sppOption, (code: BusinessError, number: number) => {
this.sppAccept()
}
}
}
- sppAccept():依赖于sppListen启动服务端监听后,接受客户端的SPP连接请求。
sppAccept() {
try {
socket.sppAccept(this.serverNumber, (code: BusinessError, number: number) => {
······
});
}
}
- msgSend():调用socket.sppWrite方法,向已连接的客户端发送消息。
msgSend() {
······
try {
socket.sppWrite(this.clientNumber, Utils.string2ArrayBuffer(this.msgValue));
this.msgList.push(new MsgShow(this.msgValue, true))
this.msgValue = '';
}
······
}
- onSppRead():注册SPP数据读取监听器,接收来自客户端的数据。
onSppRead() {
······
try {
socket.on('sppRead', this.clientNumber, (dataBuffer: ArrayBuffer) => {
let data = Utils.ArrayBuffer2String(dataBuffer);
this.msgList.push(new MsgShow(data, false))
});
this.msgReadSwitch = true;
}
}
更多关于HarmonyOS鸿蒙Next中蓝牙设备可配对成功但是连接却是一直失败,代码写在下面了,就是在连接到时候出现问题,连接不上,希望有大佬解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
1.尝试修改这里的参数:
// 配置监听参数
let option: socket.SppOptions = {
uuid: '00009999-0000-1000-8000-00805F9B34FB',
secure: true,
type: socket.SppType.SPP_RFCOMM
};
2.楼主的代码太多了 希望楼主提供一个git仓库,在仓库里面搭建一个最小页面的项目共享出来调试
git clone https://gitee.com/liuyongzhengnb/test.git
你这个项目跑不起来,
楼主你这个太长了,就不一一看了,你先看下权限配置,在config.json中配ohos.permission.BLUETOOTH权限。
{
"module": {
"reqPermissions": [
{ "name": "ohos.permission.BLUETOOTH" }
]
}
}
然后在连接前停止蓝牙扫描,因为如果资源占用会导致连接失败,前提得确保设备处于可发现模式且没有被其他占用
discoveryDeviceManager.stopDiscovery(); // 在连接前停止扫描
对了你再通过connection.getConnectedDevices()获取当前连接设备列表。检查一下已连接设备数量,别超过阈值。
别的没发现问题,关键代码优化一下再试试,前面几点别忘了确认
public async connect(device: string) {
try {
// 停止扫描释放资源
this.discoveryDeviceManager.stopDiscovery();
// 获取设备支持的Profile
const uuids = await connection.getRemoteProfileUuids(device);
if (uuids.length === 0) {
console.error('设备不支持任何可用配置文件');
return;
}
// 监听连接状态变化
this.setupProfileListeners(uuids);
// 发起连接
await connection.connectAllowedProfiles(device);
console.info('连接请求已发起');
} catch (error) {
console.error(`连接异常,错误码:${(error as BusinessError).code}, 信息:${error.message}`);
}
}
在鸿蒙Next中蓝牙连接失败可能原因:
- 设备UUID未正确配置,需与蓝牙设备厂商提供的服务UUID完全匹配
- 未添加ohos.permission.DISCOVER_BLUETOOTH和ohos.permission.MANAGE_BLUETOOTH权限
- 连接时机不当,建议在onCharacteristicWrite回调成功后发起连接
- 未正确处理设备状态变化,需监听bluetoothManager.subscribeStateChange事件
检查点:
- 确认设备支持BLE协议
- 配对后等待2-3秒再连接
- 设备是否已被其他主机连接
- 系统蓝牙服务是否正常启动
从代码来看,蓝牙配对成功但连接失败的问题可能出在以下几个关键点:
- 连接逻辑问题:
- 在PairDeviceManager的connect方法中,虽然检查了设备支持的profile,但connectAllowedProfiles()调用后没有正确处理连接状态回调
- 缺少对连接超时的处理机制
- Profile连接问题:
- 代码中只订阅了A2DP/HFP/HID的连接状态变化,但实际连接时没有等待这些profile真正连接完成
- 需要确认设备实际支持的profile与服务端是否匹配
- SPP连接问题:
- SPP连接(sppConnect)与profile连接是独立的,需要确保两者都成功
- UUID '00009999-0000-1000-8000-00805F9B34FB’需要确认是否与设备端一致
建议修改:
- 在PairDeviceManager中增强连接处理:
public async connect(device: string) {
try {
let uuids = await connection.getRemoteProfileUuids(device);
let profilesToConnect = [];
// 检查并准备需要连接的profile
if(uuids.some(uuid => uuid === constant.ProfileUuids.PROFILE_UUID_A2DP_SINK.toLowerCase())){
profilesToConnect.push(this.a2dpSrc.connect(device));
}
// 其他profile检查...
// 并行连接所有支持的profile
await Promise.all(profilesToConnect);
// 然后建立SPP连接
await new Promise<void>((resolve, reject) => {
socket.sppConnect(device, {uuid: '00009999...', ...}, (err, num) => {
if(err) reject(err);
else {
this.clientNumber = num;
resolve();
}
});
});
} catch(err) {
console.error('连接失败:', err);
throw err;
}
}
- 增加连接状态监控:
// 在连接方法中添加状态监听
this.a2dpSrc.on('connectionStateChange', (state) => {
if(state === baseProfile.ProfileConnectionState.STATE_DISCONNECTED){
console.error('A2DP连接断开');
}
});
- 检查设备兼容性:
- 确认设备确实支持声明的profile
- 检查SPP服务的UUID是否匹配
- 验证设备是否要求安全连接(secure参数)
- 错误处理:
- 添加连接超时机制
- 区分不同类型的连接错误(profile连接错误 vs SPP连接错误)
建议先在简单场景测试:
- 先单独测试profile连接
- 再单独测试SPP连接
- 最后测试完整流程
注意查看日志中具体的错误码,这对定位问题很有帮助。