24_微信小程序蓝牙-设备搜寻篇

24_微信小程序蓝牙-设备搜寻篇

注: 示例代码使用uniapp编写,下面通过uni.调用的API侧重于微信侧,等同于wx.

上一篇文章: 23_微信小程序蓝牙-权限适配篇 中已经讲清楚了uni.openBluetoothAdapter的用法,以及关于权限会出现的问题以及适配方案,只有蓝牙模块初始化成功,后续的蓝牙相关API才能调用成功,设备搜寻也不例外。

一.uni.openBluetoothAdapter封装

uni.openBluetoothAdapter一旦调用成功,如果有其他地方也需要调用时,必须先调用uni.closeBluetoothAdapteruni.openBluetoothAdapter才能被再次调用成功

在实际业务中,如果有多个地方使用了uni.openBluetoothAdapter,如果处理不当,也是会出现问题的。续接上一篇文章对uni.openBluetoothAdapter进行封装,保证uni.openBluetoothAdapter全局只会被调用一次。

/**
 * 蓝牙权限待申请
 */
const BLUETOOTH_AUTHOR_PENDING:string = "BLUETOOTH_AUTHOR_PENDING"
/**
 * 蓝牙权限被拒绝
 */
const BLUETOOTH_AUTHOR_REJECT:string = "BLUETOOTH_AUTHOR_REJECT"
/**
 * BluetoothAdapter不可用
 */
const BLUETOOTH_ADAPTER_UNAVAILABLE:string = "BLUETOOTH_ADAPTER_UNAVAILABLE"
/**
 * 蓝牙适配器可用
 */
const BLUETOOTH_ADAPTER_AVAILABLE:string = "BLUETOOTH_ADAPTER_AVAILABLE"

export interface BluetoothManager {
	on(type: string, callback: (status: string) => void): void;
	off(type: string, callback: (status: string) => void): void;
	destroy(): void;
}

function dispatchBluetoothStatus(status: string): void {
	this.statusCallbacks.forEach((func) => {
		func && func(status)
	})
}

function initializeBluetooth(): Promise<any> {
  this.status = BLUETOOTH_AUTHOR_PENDING
	dispatchBluetoothStatus.call(this, this.status)
	
	const scope:string = "scope.bluetooth"
	const openBluetoothAdapter = ():Promise<any> => {
		return uni.openBluetoothAdapter().catch((err) => {
			this.status = BLUETOOTH_ADAPTER_UNAVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.reject()
		}).then((res) => {
			this.status = BLUETOOTH_ADAPTER_AVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.resolve()
		})
	}
	
	const openSetting = () => {
		return uni.showModal({
			content: "您需要在设置中开启\"蓝牙\"选项,才可以使用蓝牙哦!",
			cancelText: "任性不去",
			confirmText: "去设置",
		}).then((res) => {
			if (res.confirm) {
				return new Promise((resolve, reject) => {
					this.openSettingResolves.push(resolve)
					uni.openSetting().catch((error) => {
						reject({
							"errMsg": "openSetting:fail system error",
							"errno": -2
						})
					})
				}).then((res) => {
					let authSetting = res.authSetting || {}
					if (authSetting[scope]) {
						return Promise.resolve()
					} else {
						return openSetting()
					}
				})
			} else {
				return Promise.reject({
					"errMsg": "authorize:fail auth deny",
					"errno": 103
				})
			}
		})
	}
	
	const getSetting = () => {
		return uni.getSetting().catch((error) => {
			return Promise.reject({
				"errMsg": "authorize:fail system error",
				"errno": -2
			})
		}).then((res) => {
			let authSetting = res.authSetting || {}
			let keys = Object.keys(authSetting)
			
			if (keys.indexOf(scope) != -1) {
				if(!authSetting[scope]) {
					return openSetting()
				} else {
					return Promise.resolve() 
				}
			} else {
				return Promise.reject({
					"errMsg": "authorize:fail auth canceled",
					"errno": -3
				})
			}
		})
	}
  
  return uni.authorize({scope: scope}).catch((err) => {
		return getSetting()
	}).catch((err) => {
		this.status = BLUETOOTH_AUTHOR_REJECT
		dispatchBluetoothStatus.call(this, this.status)
		return Promise.reject()
	}).then((res) => {
		return uni.closeBluetoothAdapter().catch((err) => Promise.resolve())
	}).then((res) => {
		return openBluetoothAdapter()
	})
}

class BluetoothManagerInstance implements BluetoothManager {
  private status:string;
	private statusCallbacks: Array<(status: string) => void> = [];
	private openSettingResolves: Array<(result:any) => void> = [];
	
	private onAppShow: (options: any) => void = (options): void => {
		uni.getSetting().then((res) => {
			if(this.openSettingResolves.length > 0) {
				this.openSettingResolves.forEach((resolveFunc) => resolveFunc(res))
				this.openSettingResolves = []
			} else {
				let authSetting = res.authSetting || {}
				let keys = Object.keys(authSetting)
				
				if(keys.indexOf("scope.bluetooth") != -1) {
					if (!authSetting["scope.bluetooth"]) {
            if(this.status != BLUETOOTH_AUTHOR_PENDING) {
							this.status = BLUETOOTH_AUTHOR_REJECT
							dispatchBluetoothStatus.call(this, this.status)
						}
					} else {
						if(this.status == BLUETOOTH_AUTHOR_REJECT) {
							initializeBluetooth.call(this);
						}
					}
				}
			}
			return Promise.resolve()
		}).catch((err) => {
			return Promise.resolve()
		})
	}

	constructor() {
		uni.onAppShow(this.onAppShow);
		initializeBluetooth.call(this);
	}
	
	on(type: string, callback: (result: any) => void): void {
		if(type == "statusChange") {
			this.statusCallbacks.push(callback)
		}
	}
	
	off(type: string, callback: (result: any) => void): void {
		if(type == "statusChange") {
      let callbackIndex = this.statusCallbacks.findIndex((item) => item == callback)
      if(callbackIndex == -1) {
        return
      }
			this.statusCallbacks.splice(callbackIndex, 1)
		}
	}
	
	destroy(): void {
		this.status = BLUETOOTH_AUTHOR_PENDING
		
		uni.closeBluetoothAdapter().catch(() => undefined)
		this.statusCallbacks = []
		
		uni.offAppShow(this.onAppShow)
	}
}

export const createBluetoothManager = ():BluetoothManager => {
	return new BluetoothManagerInstance();
}

使用的时候,只需要在App.vue中,调用createBluetoothManager初始化,就能保证全局只调用一次。

<!-- App.vue -->
<script>
import { createBluetoothManager } from '@/bluetooth/bluetooth-manager'

export default {
  globalData: {  
		bluetoothManager: undefined
  },
  onLaunch: function () {
		this.globalData.bluetoothManager = createBluetoothManager()
  },
  onShow: function () {
    console.log('App Show')
  },
  onHide: function () {
    console.log('App Hide')
  },
}
</script>
<!-- index.vue -->
<script>
	export default {
		data() {
			return {
				
			}
		},
		onLoad() {
			getApp().globalData.bluetoothManager.on("statusChange", this.onBluetoothStatusChanged)
		},
		onUnload() {
			getApp().globalData.bluetoothManager.off("statusChange", this.onBluetoothStatusChanged)
		},
		methods: {
			onBluetoothStatusChanged: function(status) {
				console.log("onBluetoothStatusChanged", status)
			}
		}
	}
</script>
二.监听系统蓝牙开关,改变蓝牙状态

注: 安卓机型需要有位置权限才能搜索到设备

只需要调用使用uni.onBluetoothAdapterStateChange即可。

注: uni.onBluetoothAdapterStateChange只需放在uni.openBluetoothAdapter调用完成后即可:

  • 安卓 12 及以上版本手机,无搜索附近设备权限附近设备开关未打开
  • iOS手机,未打开微信app访问蓝牙的开关

上述两种情况,调用uni.onBluetoothAdapterStateChange无法成功添加监听。

...

function initializeBluetooth(): Promise<any> {
  this.status = BLUETOOTH_AUTHOR_PENDING
	dispatchBluetoothStatus.call(this, this.status)
  
  const scope:string = "scope.bluetooth"
	const openBluetoothAdapter = ():Promise<any> => {
		return uni.openBluetoothAdapter().catch((err) => {
			this.status = BLUETOOTH_ADAPTER_UNAVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.reject()
		}).then((res) => {
			this.status = BLUETOOTH_ADAPTER_AVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.resolve()
		}).finally(() => {
			//关闭蓝牙适配器状态监听
			uni.offBluetoothAdapterStateChange(this.adapterStateChange)
			//开启蓝牙适配器状态监听
			uni.onBluetoothAdapterStateChange(this.adapterStateChange)
		})
	}
  
  ...
}
  
...

class BluetoothManagerInstance implements BluetoothManager {
  ...
  
  private adapterStateChange: (result: any) => void = (res) => {
		let available = (res || {}).available || false
		let discovering = (res || {}).discovering || false
		
		let bluetoothStatus = BLUETOOTH_ADAPTER_UNAVAILABLE
		if(available) {
			bluetoothStatus = BLUETOOTH_ADAPTER_AVAILABLE
		}
		
		this.status = bluetoothStatus
	}
  
  ...
  
  destroy(): void {
		this.status = BLUETOOTH_AUTHOR_PENDING
		
    //关闭蓝牙适配器状态监听
		uni.offBluetoothAdapterStateChange(this.adapterStateChange)
    
		uni.closeBluetoothAdapter().catch(() => undefined)
		this.statusCallbacks = []
		
		uni.offAppShow(this.onAppShow)
	}
}
三.搜索设备
  • uni.onBluetoothDeviceFound 回调了某个设备,则此设备会添加到 uni.getBluetoothDevices 接口获取到的数组中

  • 只需要在uni.openBluetoothAdapter调用成功后,调用uni.startBluetoothDevicesDiscovery,调用成功后,再通过uni.onBluetoothDeviceFound开启搜索到设备的监听,在回调中通过uni.getBluetoothDevices就可以拿到所有搜索到的设备了。

    ...
    
    function startScanBluetoothDevice(): Promise<any> {
    	return uni.startBluetoothDevicesDiscovery({
    		allowDuplicatesKey: false,
    		interval: 1000
    	}).catch((err) => {
    		return Promise.reject()
    	}).then(() => {
    		//添加搜索到新设备的事件的监听函数
    		uni.offBluetoothDeviceFound(this.onBluetoothDeviceFound)
    		uni.onBluetoothDeviceFound(this.onBluetoothDeviceFound)
    		return Promise.resolve()
    	})
    }
    
    function stopScanBluetoothDevice():Promise<any> {
    	//移除搜索到新设备的事件的监听函数
    	uni.offBluetoothDeviceFound(this.onBluetoothDeviceFound)
    	return uni.stopBluetoothDevicesDiscovery().catch(() => undefined)
    }
    
    function initializeBluetooth(): Promise<any> {
      
      ...
      
      return uni.authorize({scope: scope}).catch((err) => {
    		return getSetting()
    	}).catch((err) => {
    		this.status = BLUETOOTH_AUTHOR_REJECT
    		dispatchBluetoothStatus.call(this, this.status)
    		return Promise.reject()
    	}).then((res) => {
    		return uni.closeBluetoothAdapter().catch((err) => Promise.resolve())
    	}).then((res) => {
    		return openBluetoothAdapter()
    	}).then((res) => {
    		return stopScanBluetoothDevice.call(this)
    	}).then((res) => {
    		return startScanBluetoothDevice.call(this)
    	})
    }
    
    class BluetoothManagerInstance implements BluetoothManager {
      ...
      
      private onBluetoothDeviceFound: (result: any) => void = (result) => {
    		uni.getBluetoothDevices().then((res) => {
          //所有搜索到的设备
    			console.log("onBluetoothDeviceFound", res)
    		})
    	}
      
      ...
      
      destroy(): void {
    		this.status = BLUETOOTH_AUTHOR_PENDING
    		
        stopScanBluetoothDevice.call(this)
        
        //关闭蓝牙适配器状态监听
    		uni.offBluetoothAdapterStateChange(this.adapterStateChange)
        
    		uni.closeBluetoothAdapter().catch(() => undefined)
    		this.statusCallbacks = []
    		
    		uni.offAppShow(this.onAppShow)
    	}
    }
    
  • 系统蓝牙开关由开变关时,停止搜索,系统蓝牙由关变开时,重新开始搜索

    class BluetoothManagerInstance implements BluetoothManager {
      ...
      
      private adapterStateChange: (result: any) => void = (res) => {
    		let available = (res || {}).available || false
    		let discovering = (res || {}).discovering || false
    		
    		let bluetoothStatus = BLUETOOTH_ADAPTER_UNAVAILABLE
    		if(available) {
    			bluetoothStatus = BLUETOOTH_ADAPTER_AVAILABLE
    		}
        
        if(this.status != bluetoothStatus) {
    			//蓝牙开关状态改变
    			if(bluetoothStatus == BLUETOOTH_ADAPTER_AVAILABLE) {
    				//搜索设备
    				startScanBluetoothDevice.call(this)
    			} else {
    				//停止搜索设备
    				stopScanBluetoothDevice.call(this)
    			}
    		}
    		
    		this.status = bluetoothStatus
    	}
      
      ...
    }
    
  • 将搜索到的设备排序,最后回传给业务层

    ...
    
    function dispatchDeviceFound(devices: Array<any>) {
    	this.devicesCallbacks.forEach((func) => {
    		func && func(devices)
    	})
    }
    
    ...
    
    class BluetoothManagerInstance implements BluetoothManager {
      ...
      
      private devicesCallbacks: Array<(devices: Array<any>) => void> = [];
    
    	...
      
      private onBluetoothDeviceFound: (result: any) => void = (result) => {
    		uni.getBluetoothDevices().then((res) => {
    			let devices = (res || {}).devices || []
    			
    			//排序
    			devices.sort((item1, item2) => {
    				let name1 = (item1.localName || item1.name).toLowerCase()
    				let name2 = (item2.localName || item2.name).toLowerCase()
    				return name1.localeCompare(name2)
    			})
    			
    			dispatchDeviceFound.call(this, devices)
    		})
    	}
      
      ...
      
      on(type: string, callback: (result: any) => void): void {
    		if(type == "statusChange") {
    			this.statusCallbacks.push(callback)
    		} else if(type == "deviceFound") {
    			this.devicesCallbacks.push(callback)
    		}
    	}
    	
    	off(type: string, callback: (result: any) => void): void {
    		if(type == "statusChange") {
    			let callbackIndex = this.statusCallbacks.findIndex((item) => item == callback)
    			if(callbackIndex == -1) {
    				return
    			}
    			this.statusCallbacks.splice(callbackIndex, 1)
    		} else if(type == "deviceFound") {
    			let callbackIndex = this.devicesCallbacks.findIndex((item) => item == callback)
    			if(callbackIndex == -1) {
    				return
    			}
    			this.devicesCallbacks.splice(callbackIndex, 1)
    		}
    	}
      
      destroy(): void {
    		this.status = BLUETOOTH_AUTHOR_PENDING
    		
    		stopScanBluetoothDevice.call(this)
    		
    		//关闭蓝牙适配器状态监听
    		uni.offBluetoothAdapterStateChange(this.adapterStateChange)
    		
    		uni.closeBluetoothAdapter().catch(() => undefined)
    		this.statusCallbacks = []
    		this.devicesCallbacks = []
    		
    		uni.offAppShow(this.onAppShow)
    	}
    }
    
    <!-- index.vue -->
    <template>
    	<view class="index-page">
    		<view class="bluetooth-status">蓝牙状态: {{bluetoothStatus}}</view>
    		<scroll-view scroll-y class="device-list">
    			<view v-for="(item, index) in devices" class="device-item">
    				<view class="device-info">设备名称: {{item.localName || item.name || item.deviceId}}</view>
    				<view class="device-info">设备ID: {{item.deviceId}}</view>
    				<view class="device-info">RSSI: {{item.RSSI}}</view>
    			</view>
    		</scroll-view>
    	</view>
    </template>
    
    <script>
    	export default {
    		data() {
    			return {
    				bluetoothStatus: "BLUETOOTH_AUTHOR_PENDING",
    				devices: []
    			}
    		},
    		onLoad() {
    			getApp().globalData.bluetoothManager.on("statusChange", this.onBluetoothStatusChanged)
    			getApp().globalData.bluetoothManager.on("deviceFound", this.onDeviceFound)
    		},
    		onUnload() {
    			getApp().globalData.bluetoothManager.off("statusChange", this.onBluetoothStatusChanged)
    			getApp().globalData.bluetoothManager.off("deviceFound", this.onDeviceFound)
    		},
    		methods: {
    			onBluetoothStatusChanged: function(status) {
    				this.bluetoothStatus = status
    			},
    			onDeviceFound: function(devices) {
    				this.devices = devices
    			}
    		}
    	}
    </script>
    
    <style scoped>
    	.index-page {
    		width: 100%;
    		height: 100%;
    		display: flex;
    		flex-direction: column;
    		align-items: stretch;
    		justify-content: center;
    	}
    	
    	.bluetooth-status {
    		font-size: 24rpx;
    		padding: 20rpx 0;
    		margin: 0 20rpx;
    		box-sizing: border-box;
    		flex-shrink: 0;
    		border-bottom: thin solid #f2f2f2;
    	}
    	
    	.device-list {
    		flex: 1;
    		overflow: hidden;
    	}
    	
    	.device-item {
    		display: flex;
    		flex-direction: column;
    		align-items: stretch;
    		justify-content: center;
    		padding: 20rpx 0;
    		margin: 0 20rpx;
    		box-sizing: border-box;
    		background: white;
    		border-bottom: thin solid #f2f2f2;
    	}
    	
    	.device-info {
    		font-size: 28rpx;
    		margin-top: 20rpx;
    	}
    	
    	.device-info:first-child {
    		margin-top: 0;
    	}
    </style>
    

    在这里插入图片描述

四.完整代码
/**
 * 蓝牙权限待申请
 */
const BLUETOOTH_AUTHOR_PENDING:string = "BLUETOOTH_AUTHOR_PENDING"
/**
 * 蓝牙权限被拒绝
 */
const BLUETOOTH_AUTHOR_REJECT:string = "BLUETOOTH_AUTHOR_REJECT"
/**
 * BluetoothAdapter不可用
 */
const BLUETOOTH_ADAPTER_UNAVAILABLE:string = "BLUETOOTH_ADAPTER_UNAVAILABLE"
/**
 * 蓝牙适配器可用
 */
const BLUETOOTH_ADAPTER_AVAILABLE:string = "BLUETOOTH_ADAPTER_AVAILABLE"

export interface BluetoothManager {
	on(type: string, callback: (status: string) => void): void;
	off(type: string, callback: (status: string) => void): void;
	destroy(): void;
}

function dispatchDeviceFound(devices: Array<any>) {
	this.devicesCallbacks.forEach((func) => {
		func && func(devices)
	})
}

function dispatchBluetoothStatus(status: string): void {
	this.statusCallbacks.forEach((func) => {
		func && func(status)
	})
}

function startScanBluetoothDevice(): Promise<any> {
	return uni.startBluetoothDevicesDiscovery({
		allowDuplicatesKey: false,
		interval: 1000
	}).catch((err) => {
		return Promise.reject()
	}).then(() => {
		//添加搜索到新设备的事件的监听函数
		uni.offBluetoothDeviceFound(this.onBluetoothDeviceFound)
		uni.onBluetoothDeviceFound(this.onBluetoothDeviceFound)
		return Promise.resolve()
	})
}

function stopScanBluetoothDevice():Promise<any> {
	//移除搜索到新设备的事件的监听函数
	uni.offBluetoothDeviceFound(this.onBluetoothDeviceFound)
	return uni.stopBluetoothDevicesDiscovery().catch(() => undefined)
}

function initializeBluetooth(): Promise<any> {
	this.status = BLUETOOTH_AUTHOR_PENDING
	dispatchBluetoothStatus.call(this, this.status)
	
	const scope:string = "scope.bluetooth"
	const openBluetoothAdapter = ():Promise<any> => {
		return uni.openBluetoothAdapter().catch((err) => {
			this.status = BLUETOOTH_ADAPTER_UNAVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.reject()
		}).then((res) => {
			this.status = BLUETOOTH_ADAPTER_AVAILABLE
			dispatchBluetoothStatus.call(this, this.status)
			return Promise.resolve()
		}).finally(() => {
			//关闭蓝牙适配器状态监听
			uni.offBluetoothAdapterStateChange(this.adapterStateChange)
			//开启蓝牙适配器状态监听
			uni.onBluetoothAdapterStateChange(this.adapterStateChange)
		})
	}
	
	const openSetting = () => {
		return uni.showModal({
			content: "您需要在设置中开启\"蓝牙\"选项,才可以使用蓝牙哦!",
			cancelText: "任性不去",
			confirmText: "去设置",
		}).then((res) => {
			if (res.confirm) {
				return new Promise((resolve, reject) => {
					this.openSettingResolves.push(resolve)
					uni.openSetting().catch((error) => {
						reject({
							"errMsg": "openSetting:fail system error",
							"errno": -2
						})
					})
				}).then((res) => {
					let authSetting = res.authSetting || {}
					if (authSetting[scope]) {
						return Promise.resolve()
					} else {
						return openSetting()
					}
				})
			} else {
				return Promise.reject({
					"errMsg": "authorize:fail auth deny",
					"errno": 103
				})
			}
		})
	}
	
	const getSetting = () => {
		return uni.getSetting().catch((error) => {
			return Promise.reject({
				"errMsg": "authorize:fail system error",
				"errno": -2
			})
		}).then((res) => {
			let authSetting = res.authSetting || {}
			let keys = Object.keys(authSetting)
			
			if (keys.indexOf(scope) != -1) {
				if(!authSetting[scope]) {
					return openSetting()
				} else {
					return Promise.resolve() 
				}
			} else {
				return Promise.reject({
					"errMsg": "authorize:fail auth canceled",
					"errno": -3
				})
			}
		})
	}
	
	return uni.authorize({scope: scope}).catch((err) => {
		return getSetting()
	}).catch((err) => {
		this.status = BLUETOOTH_AUTHOR_REJECT
		dispatchBluetoothStatus.call(this, this.status)
		return Promise.reject()
	}).then((res) => {
		return uni.closeBluetoothAdapter().catch((err) => Promise.resolve())
	}).then((res) => {
		return openBluetoothAdapter()
	}).then((res) => {
		return stopScanBluetoothDevice.call(this)
	}).then((res) => {
		return startScanBluetoothDevice.call(this)
	})
}

class BluetoothManagerInstance implements BluetoothManager {
	
	private status:string;
	private statusCallbacks: Array<(status: string) => void> = [];
	private openSettingResolves: Array<(result:any) => void> = [];
	private devicesCallbacks: Array<(devices: Array<any>) => void> = [];
	
	private onAppShow: (options: any) => void = (options): void => {
		uni.getSetting().then((res) => {
			if(this.openSettingResolves.length > 0) {
				this.openSettingResolves.forEach((resolveFunc) => resolveFunc(res))
				this.openSettingResolves = []
			} else {
				let authSetting = res.authSetting || {}
				let keys = Object.keys(authSetting)
				
				if(keys.indexOf("scope.bluetooth") != -1) {
					if (!authSetting["scope.bluetooth"]) {
						if(this.status != BLUETOOTH_AUTHOR_PENDING) {
							this.status = BLUETOOTH_AUTHOR_REJECT
							dispatchBluetoothStatus.call(this, this.status)
						}
					} else {
						if(this.status == BLUETOOTH_AUTHOR_REJECT) {
							initializeBluetooth.call(this);
						}
					}
				}
			}
			return Promise.resolve()
		}).catch((err) => {
			return Promise.resolve()
		})
	}
	
	private adapterStateChange: (result: any) => void = (res) => {
		let available = (res || {}).available || false
		let discovering = (res || {}).discovering || false
		
		let bluetoothStatus = BLUETOOTH_ADAPTER_UNAVAILABLE
		if(available) {
			bluetoothStatus = BLUETOOTH_ADAPTER_AVAILABLE
		}
		if(this.status != bluetoothStatus) {
			//蓝牙开关状态改变
			if(bluetoothStatus == BLUETOOTH_ADAPTER_AVAILABLE) {
				//搜索设备
				startScanBluetoothDevice.call(this)
			} else {
				//停止搜索设备
				stopScanBluetoothDevice.call(this)
			}
		}
		
		this.status = bluetoothStatus
	}
	
	private onBluetoothDeviceFound: (result: any) => void = (result) => {
		uni.getBluetoothDevices().then((res) => {
			let devices = (res || {}).devices || []
			
			//排序
			devices.sort((item1, item2) => {
				let name1 = (item1.localName || item1.name).toLowerCase()
				let name2 = (item2.localName || item2.name).toLowerCase()
				return name1.localeCompare(name2)
			})
			
			dispatchDeviceFound.call(this, devices)
		})
	}
	
	constructor() {
		uni.onAppShow(this.onAppShow);
		initializeBluetooth.call(this);
	}
	
	on(type: string, callback: (result: any) => void): void {
		if(type == "statusChange") {
			this.statusCallbacks.push(callback)
		} else if(type == "deviceFound") {
			this.devicesCallbacks.push(callback)
		}
	}
	
	off(type: string, callback: (result: any) => void): void {
		if(type == "statusChange") {
			let callbackIndex = this.statusCallbacks.findIndex((item) => item == callback)
			if(callbackIndex == -1) {
				return
			}
			this.statusCallbacks.splice(callbackIndex, 1)
		} else if(type == "deviceFound") {
			let callbackIndex = this.devicesCallbacks.findIndex((item) => item == callback)
			if(callbackIndex == -1) {
				return
			}
			this.devicesCallbacks.splice(callbackIndex, 1)
		}
	}
	
	destroy(): void {
		this.status = BLUETOOTH_AUTHOR_PENDING
		
		stopScanBluetoothDevice.call(this)
		
		//关闭蓝牙适配器状态监听
		uni.offBluetoothAdapterStateChange(this.adapterStateChange)
		
		uni.closeBluetoothAdapter().catch(() => undefined)
		this.statusCallbacks = []
		this.devicesCallbacks = []
		
		uni.offAppShow(this.onAppShow)
	}
	
}

export const createBluetoothManager = ():BluetoothManager => {
	return new BluetoothManagerInstance();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值