##鸿蒙开发能力 ##HarmonyOS SDK 应用服务 ##鸿蒙金融类应用 (金融理财 # 前言 蓝牙一般分为传统蓝牙(BR/EDR),低功耗蓝牙(BLE)两种。 鸿蒙将蓝牙的功能模块分的非常细。 基本上我们会用到access进行蓝牙状态的开启和关闭,以及状态查询。 在使用connection进行传统蓝牙模式的扫描和配对。 或者再使用ble低功耗蓝牙模式进行广播,发起广播,传输数据,以及消息订阅。
Demo示例: import { access } from '@kit.ConnectivityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { BlueToothMgr } from '../manager/BlueToothMgr'; import { abilityAccessCtrl, common } from '@kit.AbilityKit'; import { connection } from '@kit.ConnectivityKit'; import { map } from '@kit.ConnectivityKit'; import { pbap } from '@kit.ConnectivityKit';
@Entry @Component struct Index {
private TAG: string = "BlueToothTest";
// 蓝牙状态 @State @Watch('onChangeBlueTooth') isStartBlueTooth: boolean = false; @State userGrant: boolean = false;
@State mListDevice: Array
async aboutToAppear() { await this.requestBlueToothPermission();
let state = access.getState();
console.log(this.TAG, "getState state: " + state);
if(state == 2){
this.isStartBlueTooth = true;
}else{
this.isStartBlueTooth = false;
}
}
private onChangeBlueTooth(){ if(!this.isStartBlueTooth){ return; } // 当前设备的蓝牙可发现状态 try { let res: boolean = connection.isBluetoothDiscovering(); console.info(this.TAG, 'isBluetoothDiscovering: ' + res); } catch (err) { console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); }
// 访问信息相关功能
try {
let mapMseProfile = map.createMapMseProfile();
console.info(this.TAG, 'MapMse success:' + JSON.stringify(mapMseProfile));
} catch (err) {
console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
// 访问电话簿相关功能
try {
let pbapServerProfile = pbap.createPbapServerProfile();
console.info(this.TAG, 'pbapServer success:' + JSON.stringify(pbapServerProfile));
} catch (err) {
console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
try {
connection.on('bluetoothDeviceFind', (data: Array<string>)=> {
console.info(this.TAG, 'data length' + JSON.stringify(data));
// 获取扫描可配对的设备列表
this.mListDevice = data;
});
connection.startBluetoothDiscovery();
} catch (err) {
console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
// 用户申请权限 async reqPermissionsFromUser(): Promise<number[]> { let context = getContext() as common.UIAbilityContext; let atManager = abilityAccessCtrl.createAtManager(); let grantStatus = await atManager.requestPermissionsFromUser(context, ['ohos.permission.ACCESS_BLUETOOTH']); return grantStatus.authResults; }
// 用户申请蓝牙权限 async requestBlueToothPermission() { let grantStatus = await this.reqPermissionsFromUser(); for (let i = 0; i < grantStatus.length; i++) { if (grantStatus[i] === 0) { // 用户授权,可以继续访问目标操作 this.userGrant = true; } } }
setBlueToothState =()=>{ try { if(!this.isStartBlueTooth){ BlueToothMgr.Ins().setBlueToothAccess(true); }else{ BlueToothMgr.Ins().setBlueToothAccess(false); } let state = access.getState(); if(state == 2){ this.isStartBlueTooth = true; }else{ this.isStartBlueTooth = false; } console.log(this.TAG, "getState state: " + state); } catch (err) { console.error(this.TAG,'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); } }
build() { RelativeContainer() { if(this.userGrant){ Text("蓝牙状态:" + this.isStartBlueTooth ? "开启" : "关闭") .id('HelloWorld') .fontSize(50) .fontWeight(FontWeight.Bold) .alignRules({ center: { anchor: 'container', align: VerticalAlign.Center }, middle: { anchor: 'container', align: HorizontalAlign.Center } }) .onClick(this.setBlueToothState)
Text("蓝牙状态:" + this.isStartBlueTooth ? "开启" : "关闭")
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(this.setBlueToothState)
}
}
.height('100%')
.width('100%')
}
@Builder ListView(){ List() { ForEach(this.mListDevice, (item: string, index: number) => { ListItem() { Row() { Text(item).fontSize(px2fp(22)).fontColor(Color.Black) } .width('100%') .height(px2vp(100)) .justifyContent(FlexAlign.Start) } }, (item: string, index: number) => JSON.stringify(item) + index) } .width('100%') .height('100%') } }
import { access, ble } from '@kit.ConnectivityKit'; import { BusinessError } from '@kit.BasicServicesKit';
export class BlueToothMgr {
private TAG: string = "BlueToothTest";
private static mBlueToothMgr: BlueToothMgr | undefined = undefined;
private advHandle: number = 0xFF; // default invalid value
public static Ins(){ if(!BlueToothMgr.mBlueToothMgr){ BlueToothMgr.mBlueToothMgr = new BlueToothMgr(); } return BlueToothMgr.mBlueToothMgr; }
// STATE_OFF 0 表示蓝牙已关闭。 // STATE_TURNING_ON 1 表示蓝牙正在打开。 // STATE_ON 2 表示蓝牙已打开。 // STATE_TURNING_OFF 3 表示蓝牙正在关闭。 // STATE_BLE_TURNING_ON 4 表示蓝牙正在打开LE-only模式。 // STATE_BLE_ON 5 表示蓝牙正处于LE-only模式。 // STATE_BLE_TURNING_OFF 6 表示蓝牙正在关闭LE-only模式。
/**
设置蓝牙访问(开关状态)
@param isAccess true: 打开蓝牙
/ setBlueToothAccess(isAccess: boolean){ try { if(isAccess){
console.info(this.TAG, 'bluetooth enableBluetooth 1'); access.enableBluetooth(); console.info(this.TAG, 'bluetooth enableBluetooth '); access.on('stateChange', (data: access.BluetoothState) => { let btStateMessage = this.switchState(data); if (btStateMessage == 'STATE_ON') { access.off('stateChange'); } console.info(this.TAG, 'bluetooth statues: ' + btStateMessage); })
}else{
console.info(this.TAG, 'bluetooth disableBluetooth 1'); access.disableBluetooth(); console.info(this.TAG, 'bluetooth disableBluetooth '); access.on('stateChange', (data: access.BluetoothState) => { let btStateMessage = this.switchState(data); if (btStateMessage == 'STATE_OFF') { access.off('stateChange'); } console.info(this.TAG, "bluetooth statues: " + btStateMessage); })
} } catch (err) { console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); } }
private switchState(data: access.BluetoothState){ let btStateMessage = ''; switch (data) { case 0:
btStateMessage += 'STATE_OFF'; break;
case 1:
btStateMessage += 'STATE_TURNING_ON'; break;
case 2:
btStateMessage += 'STATE_ON'; break;
case 3:
btStateMessage += 'STATE_TURNING_OFF'; break;
case 4:
btStateMessage += 'STATE_BLE_TURNING_ON'; break;
case 5:
btStateMessage += 'STATE_BLE_ON'; break;
case 6:
btStateMessage += 'STATE_BLE_TURNING_OFF'; break;
default:
btStateMessage += 'unknown status'; break;
} return btStateMessage; }
/**
主播蓝牙广播
/ public registerBroadcast(){ try { ble.on('advertisingStateChange', (data: ble.AdvertisingStateChangeInfo) => {
console.info(this.TAG, 'bluetooth advertising state = ' + JSON.stringify(data)); AppStorage.setOrCreate('advertiserState', data.state);
}); } catch (err) { console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); } }
/**
开启蓝牙广播
/ public async startBroadcast(valueBuffer: Uint8Array){
// 表示发送广播的相关参数。 let setting: ble.AdvertiseSetting = { // 表示广播间隔,最小值设置160个slot表示100ms,最大值设置16384个slot,默认值设置为1600个slot表示1s。 interval: 160, // 表示发送功率,最小值设置-127,最大值设置1,默认值设置-7,单位dbm。推荐值:高档(1),中档(-7),低档(-15)。 txPower: 0, // 表示是否是可连接广播,默认值设置为true,表示可连接,false表示不可连接。 connectable: true };
// BLE广播数据包的内容。 let manufactureDataUnit: ble.ManufactureData = { // 表示制造商的ID,由蓝牙SIG分配。 manufactureId: 4567, manufactureValue: valueBuffer.buffer };
let serviceValueBuffer = new Uint8Array(4); serviceValueBuffer[0] = 5; serviceValueBuffer[1] = 6; serviceValueBuffer[2] = 7; serviceValueBuffer[3] = 8;
// 广播包中服务数据内容。 let serviceDataUnit: ble.ServiceData = { serviceUuid: "00001888-0000-1000-8000-00805f9b34fb", serviceValue: serviceValueBuffer.buffer };
// 表示广播的数据包内容。 let advData: ble.AdvertiseData = { serviceUuids: ["00001888-0000-1000-8000-00805f9b34fb"], manufactureData: [manufactureDataUnit], serviceData: [serviceDataUnit], includeDeviceName: false // 表示是否携带设备名,可选参数。注意带上设备名时广播包长度不能超出31个字节。 };
// 表示回复扫描请求的响应内容。 let advResponse: ble.AdvertiseData = { serviceUuids: ["00001888-0000-1000-8000-00805f9b34fb"], manufactureData: [manufactureDataUnit], serviceData: [serviceDataUnit] };
// 首次启动广播设置的参数。 let advertisingParams: ble.AdvertisingParams = { advertisingSettings: setting, advertisingData: advData, advertisingResponse: advResponse, // 表示发送广播持续的时间。单位为10ms,有效范围为1(10ms)到65535(655350ms),如果未指定此参数或者将其设置为0,则会连续发送广播。 duration: 0 // 可选参数,若大于0,则广播发送一段时间后,则会临时停止,可重新启动发送 }
// 首次启动广播,且获取所启动广播的标识ID try { this.registerBroadcast(); this.advHandle = await ble.startAdvertising(advertisingParams); } catch (err) { console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); } }
}