HarmonyOS 鸿蒙Next中蓝牙扫描不显示和手机连接中的蓝牙怎么办啊,只显示未连接的蓝牙
HarmonyOS 鸿蒙Next中蓝牙扫描不显示和手机连接中的蓝牙怎么办啊,只显示未连接的蓝牙
3 回复
import adapterManager from '../manager/AdapterManager';
import discoveryDeviceManager from '../manager/DiscoveryDeviceManager';
import pairDeviceManager from '../manager/PairDeviceManager';
import sppClientManager from '../manager/SppClientManager';
import { access, baseProfile, connection } from '[@kit](/user/kit).ConnectivityKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
import { promptAction } from '[@kit](/user/kit).ArkUI';
import { Permissions } from '[@kit](/user/kit).AbilityKit';
import abilityAccessCtrl from '[@ohos](/user/ohos).abilityAccessCtrl';
import bundleManager from '[@ohos](/user/ohos).bundle.bundleManager';
import common from '[@ohos](/user/ohos).app.ability.common';
// 定义连接状态接口
interface IProfileConnectionState {
STATE_DISCONNECTED: number;
STATE_CONNECTING: number;
STATE_CONNECTED: number;
STATE_DISCONNECTING: number;
}
// 定义连接状态枚举
export enum ProfileConnectionState {
STATE_DISCONNECTED = 0, // 断开连接
STATE_CONNECTING = 1, // 正在连接
STATE_CONNECTED = 2, // 已连接
STATE_DISCONNECTING = 3 // 正在断开
}
// 定义常量对象并指定接口类型
export const ProfileConnectionStateConst: IProfileConnectionState = {
STATE_DISCONNECTED: ProfileConnectionState.STATE_DISCONNECTED,
STATE_CONNECTING: ProfileConnectionState.STATE_CONNECTING,
STATE_CONNECTED: ProfileConnectionState.STATE_CONNECTED,
STATE_DISCONNECTING: ProfileConnectionState.STATE_DISCONNECTING
};
// 设备信息接口
/**
* 蓝牙设备信息接口,用于描述蓝牙设备的核心属性
*/
interface BluetoothDevice {
/**
* 设备的蓝牙物理地址(MAC地址)
* 格式为"XX:XX:XX:XX:XX:XX",全球唯一,用于设备的唯一标识
* 例如:"60:66:A3:4A:D3:90"
*/
address: string;
/**
* 设备的名称(友好名称)
* 由设备广播或通过查询获取,可能为空或为默认名称(如"设备+MAC前缀")
* 例如:"MO2QMo45kBOJfIZxTD+yBJX2o"或"蓝牙音箱"
*/
name: string;
/**
* 设备的配对状态
* true表示已与当前设备完成配对,false表示未配对
*/
paired: boolean;
/**
* 设备的连接状态
* true表示当前与该设备保持连接,false表示未连接
*/
connected: boolean;
/**
* 设备类型(新增)
* 用于确定显示的图标类型
*/
type?: 'phone' | 'headset' | 'speaker' | 'car' | 'watch' | 'other';
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct BluetoothIntegrationPage {
// 蓝牙状态(使用[@State](/user/State)确保UI联动更新)
[@State](/user/State) isBluetoothOn: boolean = false;
// 扫描状态(添加[@State](/user/State)触发UI刷新)
[@State](/user/State) isScanning: boolean = false;
// 已发现设备列表
[@State](/user/State) devices: BluetoothDevice[] = [];
// 已配对设备列表
[@State](/user/State) pairedDevices: BluetoothDevice[] = [];
// 当前选中设备
[@State](/user/State) selectedDevice: string = '';
// 加载状态
[@State](/user/State) isLoading: boolean = false;
// 发送的数据
[@State](/user/State) sendData: string = '';
// 设备配对状态
[@State](/user/State) devicePairingStates: Record<string, boolean> = {}; // key: address, value: 是否正在配对
// 设备连接中状态(key: 设备address,value: 是否正在连接)
[@State](/user/State) deviceConnectingStates: Record<string, boolean> = {};
// 在类中添加配对超时处理
private pairingTimeout: Map<string, number> = new Map();
aboutToAppear() {
// 优先检查权限
this.ensureBluetoothPermissions().then((hasPermissions) => {
if (hasPermissions) {
this.initManagers(); // 初始化管理器回调
this.initBluetoothState(); // 初始化蓝牙状态
} else {
console.warn('蓝牙权限未授予,功能受限');
promptAction.showToast({ message: '请授予蓝牙权限以使用功能' });
}
// 关键修改:无论蓝牙是否开启,只要有权限就加载已配对设备
if (hasPermissions) {
this.loadPairedDevices();
}
});
}
build() {
// 使用Scroll作为作为最外层容器,实现整个页面滚动
Scroll() {
Column() {
// 标题栏
Row() {
Text('蓝牙设备管理器')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#ffffff');
}
.justifyContent(FlexAlign.Center)
.padding(16)
.backgroundColor('#1677ff')
.width('100%')
// 蓝牙开关
Row() {
Text('蓝牙状态')
.fontSize(16);
Toggle({ type: ToggleType.Switch, isOn: this.isBluetoothOn })
.onChange((checked) => this.toggleBluetooth(checked));
}
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(VerticalAlign.Center)
.padding(16)
.backgroundColor('#ffffff')
.margin({ top: 8 })
.width('100%')
// 扫描控制
Row() {
// 扫描中显示进度圈
if (this.isScanning) {
LoadingProgress()
.size({ width: 20, height: 20 })
.margin({ right: 8 });
}
Button(this.isScanning ? '停止扫描' : '开始扫描')
.onClick(() => this.isScanning ? this.stopScan() : this.startScan())
.backgroundColor(this.isScanning ? '#ff4d4f' : '#1677ff')
.padding({ left: 20, right: 20 })
.enabled(this.isBluetoothOn);
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center) // 新增:确保进度圈与按钮垂直居中
.padding(16)
.width('100%')
// 已配对设备标题
Text('已配对设备')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.padding(16)
.width('100%')
.backgroundColor('#f5f5f5');
// 已配对设备列表
List() {
ForEach(this.pairedDevices, (device: BluetoothDevice) => {
ListItem() {
this.buildDeviceItem(device)
}
}, (device: BluetoothDevice) => device.address)
}
.width('100%')
.divider({ strokeWidth: 1, color: Color.Gray })
.margin({ bottom: 16 })
// 设备列表标题
Text('已发现设备')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.padding(16)
.width('100%')
.backgroundColor('#f5f5f5');
// 设备列表
List() {
ForEach(this.devices, (device: BluetoothDevice) => {
ListItem() {
this.buildDeviceItem(device)
}
}, (device: BluetoothDevice) => device.address);
}
.width('100%')
.divider({ strokeWidth: 1, color: Color.Gray })
.margin({ bottom: 20 }) // 底部留白,避免最后一项被遮挡
}
.width('100%')
.alignItems(HorizontalAlign.Start) // 确保内容左对齐
}
.width('100%')
.height('100%')
.backgroundColor('#fafafa')
.align(Alignment.Top)
.scrollBar(BarState.Off)
}
[@Builder](/user/Builder)
buildDeviceItem(device: BluetoothDevice) {
Column() {
Row() {
// 设备图标
Image(this.getDeviceIcon(device.type))
.width(40)
.height(40)
.margin({ right: 12 })
// 设备信息区域
Column() {
Text(`${device.name}`)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor(Color.Red);
Text(`MAC地址: ${device.address}`)
.fontSize(12)
.fontColor('#666666')
.margin({ top: 4 });
}
.layoutWeight(1) // 占据剩余空间
// 操作按钮区域
Row() {
// 配对中状态
if (this.devicePairingStates[device.address]) {
LoadingProgress()
.size({ width: 20, height: 20 })
.color('#1677ff')
.margin({ right: 8 });
}
// 连接中状态(新增)
else if (this.deviceConnectingStates[device.address]) {
LoadingProgress()
.size({ width: 20, height: 20 })
.color('#1677ff')
.margin({ right: 8 });
}
// 已连接状态
else if (device.connected) {
Button('断开')
.onClick(() => this.disconnectDevice(device.address))
.backgroundColor(Color.Red)
.padding({ left: 12, right: 12 });
}
// 已配对但未连接
else if (device.paired) {
Button('连接')
.onClick(() => this.connectDevice(device.address))
.backgroundColor(Color.Green)
.padding({ left: 12, right: 12 });
}
// 未配对
else {
Button('配对')
.onClick(() => this.pairDevice(device.address))
.backgroundColor('#0050b3')
.padding({ left: 12, right: 12 })
.enabled(!this.devicePairingStates[device.address]);
}
}
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({ bottom: 8 })
// 数据发送区域(仅对已连接设备显示)
if (device.connected && this.selectedDevice === device.address) {
Row() {
TextInput({ placeholder: '输入要发送的数据', text: this.sendData })
.onChange((value) => this.sendData = value)
.height(40)
.flexGrow(1)
.border({ width: 1, color: '#dddddd' })
.padding({ left: 12 });
Button('发送')
.onClick(() => this.sendDataToDevice())
.backgroundColor('#1677ff')
.margin({ left: 8 })
.padding({ left: 16, right: 16 });
}
.alignItems(VerticalAlign.Center)
.margin({ top: 8 })
.width('100%')
}
}
.padding(16)
}
// 加载已配对设备
private loadPairedDevices() {
try {
const pairedDevices = connection.getPairedDevices();
this.pairedDevices = pairedDevices.map(address => {
let name = '';
try {
name = connection.getRemoteDeviceName(address) || '';
} catch (err) {
console.error(`获取配对设备${address}名称失败: ${(err as BusinessError).code}`);
}
const device: BluetoothDevice = {
address: address,
name: name,
paired: true,
connected: false,
type: this.detectDeviceType(name)
};
return device;
});
} catch (err) {
console.error('加载已配对设备失败: ' + (err as BusinessError).code);
}
}
// 检测设备类型
private detectDeviceType(name: string): 'phone' | 'headset' | 'speaker' | 'car' | 'watch' | 'other' {
const lowerName = name.toLowerCase();
if (lowerName.includes('phone') || lowerName.includes('手机')) {
return 'phone';
} else if (lowerName.includes('headset') || lowerName.includes('耳机')) {
return 'headset';
} else if (lowerName.includes('speaker') || lowerName.includes('音箱')) {
return 'speaker';
} else if (lowerName.includes('car') || lowerName.includes('车载')) {
return 'car';
} else if (lowerName.includes('watch') || lowerName.includes('手表')) {
return 'watch';
} else {
return 'other';
}
}
// 初始化管理器回调(核心:复用管理器的事件监听)
private initManagers() {
// 1. 蓝牙状态变化:复用AdapterManager的回调
const originalAdapterCallback = adapterManager.onReceiveEvent;
adapterManager.onReceiveEvent = (state: access.BluetoothState) => {
originalAdapterCallback(state); // 保留管理器原有日志
// 同步页面蓝牙状态
this.isBluetoothOn = state === access.BluetoothState.STATE_ON;
if (!this.isBluetoothOn) {
console.warn('【页面】蓝牙已关闭,停止扫描并清空设备');
this.stopScan();
this.devices = [];
}
};
// 2. 设备发现:复用DiscoveryDeviceManager的回调
const originalDiscoveryCallback = discoveryDeviceManager.onReceiveEvent;
discoveryDeviceManager.onReceiveEvent = async (addresses: string[]) => {
originalDiscoveryCallback(addresses); // 保留管理器原有日志
console.warn(`【页面】发现新设备,共${addresses.length}个`);
for (const address of addresses) {
if (!this.devices.some(device => device.address === address) &&
!this.pairedDevices.some(device => device.address === address)) {
let deviceName = ''; // 无名称时默认空字符串(不再用MAC替代)
try {
// 仅保留实际获取到的名称,无名称则为空
deviceName = await connection.getRemoteDeviceName(address) || '';
} catch (err) {
console.error(`【页面】获取设备${address}名称失败: ${(err as BusinessError).code}`);
}
// :仅添加设备名称不为空的设备
if (deviceName.trim() !== '') {
// 添加设备到列表
const newDevice: BluetoothDevice = {
address,
name: deviceName,
paired: false,
connected: false,
type: this.detectDeviceType(deviceName)
};
this.devices = [...this.devices, newDevice];
// 打印设备详细信息
console.warn(`【页面】发现设备 - 名称: ${deviceName}, MAC地址: ${address}`);
this.checkDevicePairState(address); // 检查配对状态
} else {
console.warn(`【页面】设备${address}名称为空,不显示该设备`);
}
}
}
};
// 3. 配对状态变化:复用PairDeviceManager的回调
const originalPairCallback = pairDeviceManager.onBondStateEvent;
pairDeviceManager.onBondStateEvent = (data: connection.BondStateParam) => {
originalPairCallback(data);
// 清除加载状态
const deviceAddress = data.deviceId;
this.devicePairingStates[deviceAddress] = false;
// 清除配对超时
const timeoutId = this.pairingTimeout.get(data.deviceId);
if (timeoutId) {
clearTimeout(timeoutId);
this.pairingTimeout.delete(data.deviceId);
}
const index = this.devices.findIndex(device => device.address === data.deviceId);
if (index !== -1) {
const device = this.devices[index];
const isPaired = data.state === connection.BondState.BOND_STATE_BONDED;
// 更新设备配对状态
const newDevices = [...this.devices];
newDevices[index].paired = isPaired;
this.devices = newDevices;
// 如果配对成功,添加到已配对列表
if (isPaired) {
const newPairedDevice: BluetoothDevice = {
address: device.address,
name: device.name,
paired: true,
connected: device.connected,
type: this.detectDeviceType(device.name)
};
this.pairedDevices = [...this.pairedDevices, newPairedDevice];
// 从发现列表中移除
this.devices = this.devices.filter(d => d.address !== device.address);
}
// 显示配对结果
if (isPaired) {
promptAction.showToast({ message: `与 ${device.name} 配对成功` });
} else {
console.error(`【页面】配对失败,设备: ${deviceAddress}, 状态码: ${data.state}`);
promptAction.showToast({ message: `与 ${device.name} 配对失败,请重试` });
}
}
};
// 4. SPP接收数据回调(补充管理器的read方法)
const originalSppRead = sppClientManager.read;
sppClientManager.read = (dataBuffer: ArrayBuffer) => {
originalSppRead(dataBuffer); // 保留管理器原有日志
// 解析接收的数据并提示
// 修复类型错误:明确类型转换
const data = new Uint8Array(dataBuffer);
// 将 Uint8Array 转换为 number[]
const charCodes: number[] = Array.from(data);
const text = String.fromCharCode(...charCodes);
promptAction.showToast({ message: `收到数据: ${text}` });
console.warn(`【页面】收到数据: ${text}`);
};
// 5. 监听连接状态变化
pairDeviceManager.onProfileConnectStateChange = (deviceAddress: string, state: baseProfile.StateChangeParam) => {
console.warn(`【页面】连接状态变化: ${deviceAddress} -> ${state.state}`);
// 根据状态更新连接中状态
if (state.state === ProfileConnectionStateConst.STATE_CONNECTED) {
// 连接成功:取消连接中状态
this.deviceConnectingStates[deviceAddress] = false;
promptAction.showToast({ message更多关于HarmonyOS 鸿蒙Next中蓝牙扫描不显示和手机连接中的蓝牙怎么办啊,只显示未连接的蓝牙的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,蓝牙扫描仅显示未连接设备而无法识别已配对手机,通常由以下原因导致:系统蓝牙缓存未更新或设备可见性设置问题。请进入设置-蓝牙,关闭蓝牙功能后重新开启,强制刷新设备列表。同时确认目标手机蓝牙处于可被发现模式,且未与其他设备保持活跃连接。若问题持续,尝试清除鸿蒙系统蓝牙共享数据:设置-应用管理-系统应用-蓝牙-存储-删除数据。此操作不会影响已配对信息,但会重置扫描记录。设备需在有效通信范围内(建议10米内无障碍)。
在HarmonyOS Next中,蓝牙扫描仅显示未连接设备是正常行为。系统设计上,已连接的蓝牙设备通常不会重复出现在扫描结果中,以避免干扰用户操作。
建议通过以下步骤排查:
- 进入「设置」-「蓝牙」查看已配对设备列表,已连接的设备会在此显示状态
- 确认目标设备未被其他终端占用连接(蓝牙设备通常只能保持一个活跃连接)
- 尝试关闭/重启蓝牙功能,或重启设备刷新蓝牙服务
- 如需要重新连接,建议在已配对列表中删除设备后重新扫描配对
若问题持续存在,可检查系统版本更新或提交错误日志反馈。该设计符合主流蓝牙协议规范,能确保扫描界面的简洁性。

