手机同时能连接几个蓝牙(蓝牙模块因特网设)

小科普 138

本示例演示了如何对蓝牙进行基本操作, 传统蓝牙本机管理: 主要是针对蓝牙本机的基本操作,包括:打开和关闭蓝牙、设置和获取本机蓝牙名称、扫描和取消扫描周边蓝牙设备、获取本机蓝牙profile对其他设备的连接状态、获取本机蓝牙已配对的蓝牙设备列表。 传统蓝牙远端管理操作: 主要是针对远端蓝牙设备的基本操作,包括:获取远端蓝牙设备地址、类型、名称和配对状态,以及向远端设备发起配对。 传统蓝牙和BLE的的概念请参考 蓝牙开发概述 还有一个小知识点, 调用蓝牙的打开接口需要ohos.permission.USE_BLUETOOTH权限, 调用蓝牙扫描接口需要ohos.permission.LOCATION权限和ohos.permission.DISCOVER_BLUETOOTH权限。

2.搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。 如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。 下载源码后,使用DevEco Studio 打开项目,模拟器运行即可。 真机运行需要将config.json中的buddleName修改为自己的,如果没有请到AGC上进行配置,参见 使用模拟器进行调试 。

3.代码结构

4.实例讲解

4.1.界面布局

4.2.后台代码

4.2.1 涉及的相关类

SDK提供的核心类: BluetoothHost.java//蓝牙主机,可以管理蓝牙,提供了蓝牙的基本操作,打开/关闭/获取状态等。BluetoothRemoteDevice.java//蓝牙对象,用于建立与对端设备的连接并查询名称、设备类型和配对状态等信息。

自定义的类:BluetoothItemProvider.java//蓝牙设备列表项提供程序BluetoothEventListener.java//蓝牙事件监听接口 BluetoothPlugin.java//蓝牙插件 BluetoothDevice.java//蓝牙对象简易模型

4.2.2 BluetoothPlugin.java 蓝牙插件提供的功能

a.初始化BluetoothHost蓝牙主机对象getDefaultHost

/**
* 初始化蓝牙主机对象和监听器
* Initializes the Bluetooth Host on device.
* @param eventListener interface to update the Bluwettoth events
*/publicvoidinitializeBluetooth(BluetoothEventListener eventListener){
bluetoothEventListener = eventListener;
btHost = BluetoothHost.getDefaultHost(mainSliceContext);
LogUtil.info(TAG,"initializeBluetooth, btHost:"+btHost);
}

b.开启/关闭蓝牙/获取蓝牙状态enableBt/disableBt/getBtState

/**
* 开启蓝牙
* 低功耗蓝牙(BLE ,Bluetooth Low Energy),LE是2010年才提出的
* 经典蓝牙(classic Bluetooth),包括BR,EDR和HS(AMP)三种模式
* Enables the Bluetooth on device.
*/publicvoidenableBluetooth() {LogUtil.info("enableBluetooth","getBtState:"+btHost.getBtState());//获取蓝牙主机的状态if(btHost.getBtState() == STATE_OFF ||
btHost.getBtState() == STATE_TURNING_OFF ||
btHost.getBtState() ==STATE_BLE_ON) {LogUtil.info("enableBluetooth","enableBt:"+btHost.getBtState());//开启蓝牙btHost.enableBt();
}//事件通知蓝牙状态发生改变bluetoothEventListener.notifyBluetoothStatusChanged(btHost.getBtState());
}/**
* 关闭蓝牙
* Disables the Bluetooth on device.
*/publicvoiddisableBluetooth() {if(btHost.getBtState() == STATE_ON || btHost.getBtState() == STATE_TURNING_ON) {btHost.disableBt();
}bluetoothEventListener.notifyBluetoothStatusChanged(btHost.getBtState());
}/**
* 获取蓝牙状态
* Obtains the status of the Bluetooth on device.
* @return status of Bluetooth on device
*/publicintgetBluetoothStatus() {LogUtil.info("getBluetoothStatus","getBluetoothStatus:"+btHost.getBtState());//获取蓝牙状态returnbtHost.getBtState();
}

c.开始蓝牙发现startBtDiscovery

还要注意的是蓝牙发现操作需要申请位置权限。

/**
* 开始蓝牙发现
* Scans the currently available bluetooth devices
*/publicvoidstartBtDiscovery(){if(!btHost.isBtDiscovering()) {//开始发现设备,大约需要12.8sbtHost.startBtDiscovery();
}
}/**
*判断是否有权限
*/privatebooleanhasPermission(){returnmainSliceContext.verifySelfPermission(Constants.PERM_LOCATION) == IBundleManager.PERMISSION_GRANTED;
}/**
* 启动蓝牙扫描
* Scans the currently available bluetooth devices
*/publicvoidstartBtScan(){
LogUtil.info("startBtScan","getBtState:"+btHost.getBtState());intbtStatus = btHost.getBtState();if(btStatus == STATE_ON) {if(hasPermission()) {
startBtDiscovery();
}else{
requestPermission();
}
}
}

d.蓝牙设备配对及获取已配对的设备列表startPair/getPairedDevices

/**
* 启动与给定地址的蓝牙设备配对。
* initiate pairing with bluetooth device of given address.
*@parampairAddress address of the bluetooth device
*/publicvoid startPair(String pairAddress) {
Optional optBluetoothDevice = getSelectedDevice(pairAddress);
optBluetoothDevice.ifPresent(BluetoothRemoteDevice::startPair);
}/**
* 获取要配对的设备
*@parampairAddress
*@return*/privateOptional getSelectedDevice(String pairAddress) {if(pairAddress !=null&& !pairAddress.isEmpty()) {for(BluetoothRemoteDevice device : availableDevices) {if(device.getDeviceAddr().equals(pairAddress)) {returnOptional.ofNullable(device);
}
}
}returnOptional.empty();
}/**
* 获取已配对的蓝牙设备列表
* Obtains the paired Bluetooth device list.
*@returnpaired Bluetooth devices
*/publicList getPairedDevices() {//btHost.getPairedDevices()Set pairedDevices =newHashSet<>(btHost.getPairedDevices());returngetBluetoothDevices(pairedDevices);
}

e.蓝牙事件的订阅/取消 及 相关事件的处理

在处理蓝牙事件的同时,通过BluetoothEventListener通知MainAbilitySlice。

/**
* 订阅蓝牙事件
* Subscribe for Events of Bluetooth using CommonEvents
*/publicvoidsubscribeBluetoothEvents(){
MatchingSkills matchingSkills =newMatchingSkills();//表示蓝牙状态改变时上报的事件。matchingSkills.addEvent(BluetoothHost.EVENT_HOST_STATE_UPDATE);//指示蓝牙扫描开始时报告的事件。matchingSkills.addEvent(BluetoothHost.EVENT_HOST_DISCOVERY_STARTED);//指示蓝牙扫描完成时报告的事件。matchingSkills.addEvent(BluetoothHost.EVENT_HOST_DISCOVERY_FINISHED);//表示发现远程蓝牙设备时上报的事件。matchingSkills.addEvent(BluetoothRemoteDevice.EVENT_DEVICE_DISCOVERED);//远程蓝牙设备配对时上报的事件。matchingSkills.addEvent(BluetoothRemoteDevice.EVENT_DEVICE_PAIR_STATE);//用于创建 CommonEventSubscriber 实例并传递 subscribeInfo 参数的构造函数。CommonEventSubscribeInfo subscribeInfo =newCommonEventSubscribeInfo(matchingSkills);//订阅者commonEventSubscriber =newCommonEventSubscriber(subscribeInfo) {@OverridepublicvoidonReceiveEvent(CommonEventData commonEventData){
Intent intent = commonEventData.getIntent();
handleIntent(intent);
}
};try{//完成订阅CommonEventManager.subscribeCommonEvent(commonEventSubscriber);
}catch(RemoteException e) {
LogUtil.error(TAG,"RemoteException while subscribe bluetooth events.");
}
}/**
* 取消订阅蓝牙事件
* UnSubscribe for Bluetooth Events
*/publicvoidunSubscribeBluetoothEvents(){if(commonEventSubscriber !=null) {try{
CommonEventManager.unsubscribeCommonEvent(commonEventSubscriber);
}catch(RemoteException e) {
LogUtil.error(TAG,"RemoteException while unsubscribing bluetooth events.");
}
commonEventSubscriber =null;
}
}privatevoidhandleIntent(Intent intent){if(intent ==null) {return;
}

String action = intent.getAction();switch(action) {//状态更新caseBluetoothHost.EVENT_HOST_STATE_UPDATE:
handleHostStateUpdate();break;//扫描开始caseBluetoothHost.EVENT_HOST_DISCOVERY_STARTED:
handleDeviceDiscoveryState(true);break;//表示发现远程蓝牙设备时上报的事件。caseBluetoothRemoteDevice.EVENT_DEVICE_DISCOVERED:
handleBluetoothDeviceDiscovered(intent);break;// 扫描完成caseBluetoothHost.EVENT_HOST_DISCOVERY_FINISHED:
handleDeviceDiscoveryState(false);break;//表示远程蓝牙设备配对时上报的事件。caseBluetoothRemoteDevice.EVENT_DEVICE_PAIR_STATE:
handleDevicePairState(intent);break;default:
LogUtil.info(TAG,"Action not handled : "+ action);
}
}privatevoidhandleDevicePairState(Intent intent){
BluetoothRemoteDevice btRemoteDevice = intent.getSequenceableParam(BluetoothRemoteDevice.REMOTE_DEVICE_PARAM_DEVICE);if(btRemoteDevice.getPairState() == BluetoothRemoteDevice.PAIR_STATE_PAIRED) {//更新2个设备列表updateAvailableDeviceList(btRemoteDevice);
updatePairedDeviceList();
}
}privatevoidhandleDeviceDiscoveryState(booleanisStarted){//处理扫描状态变化事件通知bluetoothEventListener.notifyDiscoveryState(isStarted);
}/**
* 处理蓝牙状态变化通知
*/privatevoidhandleHostStateUpdate(){intstatus = getBluetoothStatus();
bluetoothEventListener.notifyBluetoothStatusChanged(status);
}/**
* 处理蓝牙发现事件
*@paramintent
*/privatevoidhandleBluetoothDeviceDiscovered(Intent intent){
BluetoothRemoteDevice btRemoteDevice =
intent.getSequenceableParam(BluetoothRemoteDevice.REMOTE_DEVICE_PARAM_DEVICE);//未配对的设备if(btRemoteDevice.getPairState() != BluetoothRemoteDevice.PAIR_STATE_PAIRED) {//发现后添加到可用的蓝牙设备availableDevices.add(btRemoteDevice);
}
bluetoothEventListener.updateAvailableDevices(getAvailableDevices());
}/**
* 更新可用设备列表
*@paramremoteDevice
*/privatevoidupdateAvailableDeviceList(BluetoothRemoteDevice remoteDevice){//移除以配对的蓝牙availableDevices.removeIf(device -> device.getDeviceAddr().equals(remoteDevice.getDeviceAddr()));
bluetoothEventListener.updateAvailableDevices(getAvailableDevices());
}privatevoidupdatePairedDeviceList(){//刷新已配对的蓝牙列表bluetoothEventListener.updatePairedDevices(getPairedDevices());
}publicListgetAvailableDevices(){returngetBluetoothDevices(availableDevices);
}/**
* 获取已配对的蓝牙设备列表
* Obtains the paired Bluetooth device list.
*@returnpaired Bluetooth devices
*/publicListgetPairedDevices(){//btHost.getPairedDevices()Set pairedDevices =newHashSet<>(btHost.getPairedDevices());returngetBluetoothDevices(pairedDevices);
}privateListgetBluetoothDevices(Set remoteDeviceList){
List btDevicesList =newArrayList<>();if(remoteDeviceList !=null) {//btDevicesList = remoteDeviceList.stream().map(BluetoothDevice::new).collect(Collectors.toList());
}returnbtDevicesList;
}

4.2.3BluetoothEventListener.java 自定义的蓝牙事件监听器接口

publicinterfaceBluetoothEventListener{voidupdateAvailableDevices(List bluetoothDevice);voidupdatePairedDevices(List bluetoothDevice);voidnotifyBluetoothStatusChanged(intbluetoothStatus);voidnotifyDiscoveryState(booleanisStarted);
}

4.2.4 BluetoothItemProvider.java 蓝牙设备列表提供程序

这个可以作为一个标准件了,每个ListContainer都可以用它,包括了列表的通用操作,像数据更新,点击事件等。

publicclassBluetoothItemProviderextendsBaseItemProvider{privatefinalAbilityContext context;privateList bluetoothDeviceList;publicBluetoothItemProvider(AbilityContext context, List itemList){this.context = context;
bluetoothDeviceList = itemList;
}@OverridepublicintgetCount(){returnbluetoothDeviceList.size();
}@OverridepublicObjectgetItem(intposition){returnbluetoothDeviceList.get(position);
}@OverridepubliclonggetItemId(intposition){returnposition;
}@OverridepublicComponentgetComponent(intposition, Component component, ComponentContainer componentContainer){returngetRootComponent(position);
}privateComponentgetRootComponent(intposition){//List item 布局组件Component rootComponent = LayoutScatter.getInstance(context)
.parse(ResourceTable.Layout_list_item,null,false);

Text deviceName = (Text) rootComponent.findComponentById(ResourceTable.Id_bluetooth_device_name);//蓝牙设备名称BluetoothDevice bluetoothDevice = bluetoothDeviceList.get(position);
deviceName.setText(bluetoothDevice.getName());//设置点击监听事件,开始配对rootComponent.setClickedListener(component -> {
LogUtil.info("BluetoothItemProvider","startPair:"+ bluetoothDevice.getAddress());//表示对端设备未配对。if(bluetoothDevice.getPairState() == BluetoothRemoteDevice.PAIR_STATE_NONE) {//启动与给定地址的蓝牙设备配对。BluetoothPlugin.getInstance(context).startPair(bluetoothDevice.getAddress());
}
});returnrootComponent;
}/**
* 更新蓝牙设备列表
* updates available Bluetooth devices in UI
*
*@paramdevices list of Bluetooth devices
*/publicvoidupdateDeviceList(List devices){
bluetoothDeviceList = devices;
notifyDataChanged();
}
}

4.2.5 MainAbilitySlice.java 主能力页面操作

a.首先是实现了几个相关的接口Component.ClickedListener 用于实现按钮的点击事件 BluetoothEventListener 用于实现蓝牙事件通知的处理CheckedStateChangedListener 用于实现switch开关的处理

publicclassMainAbilitySliceextendsAbilitySliceimplementsComponent.ClickedListener,BluetoothEventListener,AbsButton.CheckedStateChangedListener{

b.初始化工作

在onActive生命周期函数中

初始化蓝牙插件/初始化容器列表/初始化组件/订阅蓝牙事件

/**
* 初始化蓝牙插件
*/privatevoidinitializeBluetoothHost(){//BluetoothPlugin.getInstance(this).initializeBluetooth(this);
}privatevoidinitComponents(){//开始发现 按钮,用来搜索附件的蓝牙设备Button btnStartDiscovery = (Button) findComponentById(ResourceTable.Id_btn_start_discovery);//因为implements Component.ClickedListener 所以可以这样写btnStartDiscovery.setClickedListener(this);

initListContainer();//蓝牙状态文本组件textBluetoothStatus = (Text) findComponentById(ResourceTable.Id_bluetooth_status);//蓝牙开关组件bluetoothSwitch = (Switch) findComponentById(ResourceTable.Id_bt_switch);//设置状态监听事件bluetoothSwitch.setCheckedStateChangedListener(this);//根据系统蓝牙状态设置开关updateBluetoothStatus(BluetoothPlugin.getInstance(this).getBluetoothStatus());//附件的蓝牙设备容器列表containerLists = (DirectionalLayout) findComponentById(ResourceTable.Id_container_lists);//根据蓝牙状态控制是否显示附件的蓝牙设备容器列表containerLists.setVisibility(isBluetoothEnabled() ? Component.VISIBLE : Component.HIDE);//环形进度条组件progressBar = (ProgressBar) findComponentById(ResourceTable.Id_progressbar);
}/**
* 订阅蓝牙事件
*/privatevoidsubscribeBluetoothEvents(){//BluetoothPlugin.getInstance(this).subscribeBluetoothEvents();
}/**
* 初始化容器列表
*/privatevoidinitListContainer(){
ListContainer availableDevicesContainer =
(ListContainer) findComponentById(ResourceTable.Id_list_available_devices);//1.获取可用的蓝牙设备availableDevicesItemProvider =newBluetoothItemProvider(this,
BluetoothPlugin.getInstance(this).getAvailableDevices());//设置提供程序availableDevicesContainer.setItemProvider(availableDevicesItemProvider);//2.获取已配对的蓝牙设备ListContainer pairedDevicesContainer = (ListContainer) findComponentById(ResourceTable.Id_list_paired_devices);
pairedDevicesItemProvider =newBluetoothItemProvider(this,
BluetoothPlugin.getInstance(this).getPairedDevices());//设置提供程序pairedDevicesContainer.setItemProvider(pairedDevicesItemProvider);
}/**
* 更新蓝牙状态开关和文本
*@parambluetoothStatus
*/privatevoidupdateBluetoothStatus(intbluetoothStatus){
LogUtil.info("MainAbilitySlice","updateBluetoothStatus:"+ bluetoothStatus);//开关bluetoothSwitch.setChecked(isBluetoothEnabled());//状态文本textBluetoothStatus.setText(getBluetoothStatusString(bluetoothStatus));
}/**
* 显示环形进度条
* 用定时器实现了一个进度条,遗憾的是有一定的卡顿
*@paramisShow
*/privatevoidshowProgressBar(booleanisShow){
LogUtil.info("MainAbilitySlice","isShow:"+ isShow);
LogUtil.info("MainAbilitySlice","timer="+ timer);if(isShow){//显示进度条progressBar.setVisibility(Component.VISIBLE);if(timer==null){
timer =newTimer();
}if(timerTask==null){
timerTask=newTimerTask() {@Overridepublicvoidrun(){if(percent==10){
percent=1;
progressBar.setProgressValue(0);
}else{
percent++;
}
LogUtil.info("MainAbilitySlice","percent:"+ percent);
getContext().getUITaskDispatcher().asyncDispatch(newRunnable() {@Overridepublicvoidrun(){
progressBar.setProgressValue(percent*10);
}
});
}
};//timer.schedule(timerTask,0,1000);
}
}else{//隐藏进度条progressBar.setProgressValue(0);
progressBar.setVisibility(Component.HIDE);if(timer!=null){
LogUtil.info("MainAbilitySlice","timer set null");
timer.cancel();
timerTask.cancel();
timer=null;
timerTask=null;
}
}

}/**
* 获取蓝牙状态
*@return*/privatebooleanisBluetoothEnabled(){intstatus = BluetoothPlugin.getInstance(this).getBluetoothStatus();
LogUtil.info("isBluetoothEnabled","isBluetoothEnabled:"+status);returnstatus == BluetoothHost.STATE_ON;
}privateStringgetBluetoothStatusString(intbluetoothStatus){
LogUtil.info("bluetoothStatus","bluetoothStatus:"+bluetoothStatus);switch(bluetoothStatus) {caseBluetoothHost.STATE_OFF:caseBluetoothHost.STATE_BLE_TURNING_OFF://disabled 不可用returnConstants.BT_DISABLED;caseBluetoothHost.STATE_TURNING_ON://turning on 开启returnConstants.BT_TURNING_ON;caseBluetoothHost.STATE_ON://enabled 可用的returnConstants.BT_ENABLED;caseBluetoothHost.STATE_TURNING_OFF://turning off 关闭returnConstants.BT_TURNING_OFF;default://undefined 未定义returnConstants.BT_UNDEFINED;
}
}

c.实现BluetoothEventListener接口相关函数

@OverridepublicvoidupdateAvailableDevices(List list){//implements BluetoothEventListener//更新容器数据availableDevicesItemProvider.updateDeviceList(list);
}@OverridepublicvoidupdatePairedDevices(List list){//implements BluetoothEventListener//更新容器数据pairedDevicesItemProvider.updateDeviceList(list);
}@OverridepublicvoidnotifyBluetoothStatusChanged(intbluetoothStatus){
LogUtil.info("notifyBluetoothStatusChanged","bluetoothStatus:"+bluetoothStatus);//蓝牙状态改变事件通知updateBluetoothStatus(bluetoothStatus);
}@OverridepublicvoidnotifyDiscoveryState(booleanisStarted){//蓝牙发现状态的事件通知showProgressBar(isStarted);
}

d.实现CheckedStateChangedListener接口相关函数

@Overridepublic void onCheckedChanged(AbsButton absButton, boolean isChecked) {//开关状态改变事件触发if(absButton.getId() == ResourceTable.Id_bt_switch && containerLists != null) {if(isChecked) {LogUtil.info("onCheckedChanged","enableBluetooth");//开启蓝牙BluetoothPlugin.getInstance(this).enableBluetooth();containerLists.setVisibility(Component.VISIBLE);
}else{//关闭蓝牙BluetoothPlugin.getInstance(this).disableBluetooth();containerLists.setVisibility(Component.HIDE);

}
}
}

e.实现ClickedListener接口相关函数,开始发现蓝牙

@Overridepublic void onClick(Component component) {LogUtil.info("MainAbilitySlice","startBtScan...");//开始发现 扫描蓝牙设备if(component.getId() == ResourceTable.Id_btn_start_discovery) {LogUtil.info("MainAbilitySlice","startBtScan...");BluetoothPlugin.getInstance(this).startBtScan();
}
}

——————

原创:老王丨鸿蒙hms开发者高级认证持证人!提供鸿蒙关键技术解析及软件开发相关技术干货~【公众号:鸿蒙开发者老王】

上一篇:

下一篇:

  推荐阅读

分享