初始化一些参数
const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter') as any
const Intent = plus.android.importClass('android.content.Intent') as any
const IntentFilter = plus.android.importClass('android.content.IntentFilter') as any
const BluetoothDevice = plus.android.importClass('android.bluetooth.BluetoothDevice') as any
const UUID = plus.android.importClass('java.util.UUID') as any
const Toast = plus.android.importClass('android.widget.Toast') as any
//连接串口设备的 UUID
const MY_UUID = UUID.fromString('00001101-0000-1000-8000-00805F9B34FB')
const invoke = plus.android.invoke
const btAdapter = BluetoothAdapter.getDefaultAdapter()
const activity = plus.android.runtimeMainActivity() as any
let btSocket: any = null
let btInStream: any = null
let btOutStream: any = null
let setIntervalId = 0
let btFindReceiver: any = null //蓝牙搜索广播接收器
let btStatusReceiver: any = null //蓝牙状态监听广播
interface BlueToothToolStateType {
bluetoothEnable: boolean
bluetoothState: string
discoveryDeviceState: boolean
readThreadState: boolean
}
interface BlueToothTooloptionsType {
listenBTStatusCallback: (arg?: any) => void
discoveryDeviceCallback: (arg?: any) => void
discoveryFinishedCallback: () => void
readDataCallback: (arg?: any) => void
connExceptionCallback: (arg?: any) => void
}
构建构造函数
export class BlueToothTool {
private state: BlueToothToolStateType = {
bluetoothEnable: false, //蓝牙是否开启
bluetoothState: '', //当前蓝牙状态
discoveryDeviceState: false, //是否正在搜索蓝牙设备
readThreadState: false, //蓝牙设备名称
}
private options: BlueToothTooloptionsType = {
/**
* 监听蓝牙状态回调
* @param {String} state
*/
listenBTStatusCallback: function () {},
/**
* 搜索到新的蓝牙设备回调
* @param {Device} newDevice
*/
discoveryDeviceCallback: function () {},
/**
* 蓝牙搜索完成回调
*/
discoveryFinishedCallback: function () {},
/**
* 接收到数据回调
* @param {Array} dataByteArr
*/
readDataCallback: function () {},
/**
* 蓝牙连接中断回调
* @param {Exception} e
*/
connExceptionCallback: function () {},
}
constructor() {}
Init(setOptions: any) {
Object.assign(this.options, setOptions)
this.state.bluetoothEnable = this.GetBluetoothStatus()
this.ListenBluetoothStatus()
}
ShortToast(msg: string) {
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show()
}
/**
* 是否支持蓝牙
* @return {boolean}
*/
IsSupportBluetooth() {
if (btAdapter != null) {
return true
}
return false
}
/**
* 获取蓝牙的状态
* @return {boolean} 是否已开启
*/
GetBluetoothStatus() {
if (btAdapter != null) {
return btAdapter.isEnabled()
}
return false
}
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
CloseBtSocket() {
this.state.readThreadState = false
if (!btSocket) {
return
}
try {
btSocket.close()
} catch (e) {
console.error(e)
btSocket = null
}
}
/**
* 取消发现
*/
CancelDiscovery() {
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery()
}
if (btFindReceiver != null) {
activity.unregisterReceiver(btFindReceiver)
btFindReceiver = null
}
this.state.discoveryDeviceState = false
}
/**
* 打开蓝牙
* @param activity
* @param requestCode
*/
TurnOnBluetooth() {
if (btAdapter == null) {
this.ShortToast('没有蓝牙')
return
}
if (!btAdapter.isEnabled()) {
if (activity == null) {
this.ShortToast('未获取到activity')
return
} else {
const intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
const requestCode = 1
activity.startActivityForResult(intent, requestCode)
return
}
} else {
this.ShortToast('蓝牙已经打开')
}
}
/**
* 关闭蓝牙
*/
TurnOffBluetooth() {
if (btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable()
}
if (btFindReceiver != null) {
try {
activity.unregisterReceiver(btFindReceiver)
} catch (e) {
console.log('TurnOffBluetooth - Err', e)
}
btFindReceiver = null
}
this.state.bluetoothEnable = false
this.CancelDiscovery()
this.CloseBtSocket()
if (btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable()
this.ShortToast('蓝牙关闭成功')
} else {
this.ShortToast('蓝牙已经关闭')
}
}
/**
* 获取已经配对的设备
* @return {Array} connetedDevices
*/
GetPairedDevices() {
const pairedDevices: any[] = []
//蓝牙连接android原生对象,是一个set集合
let pairedDevicesAndroid = null
if (btAdapter != null && btAdapter.isEnabled()) {
pairedDevicesAndroid = btAdapter.getBondedDevices()
} else {
this.ShortToast('蓝牙未开启')
}
if (!pairedDevicesAndroid) {
return pairedDevices
}
//遍历连接设备的set集合,转换为js数组
const it = invoke(pairedDevicesAndroid, 'iterator')
while (invoke(it, 'hasNext')) {
const device = invoke(it, 'next')
pairedDevices.push({
name: invoke(device, 'getName'),
address: invoke(device, 'getAddress'),
})
}
return pairedDevices
}
/**
* 发现设备
*/
DiscoveryNewDevice() {
if (btFindReceiver != null) {
try {
activity.unregisterReceiver(btFindReceiver)
} catch (e) {
console.error(e)
}
btFindReceiver = null
this.CancelDiscovery()
}
const Build = plus.android.importClass('android.os.Build') as any
//6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
if (Build.VERSION.SDK_INT >= 6.0) {
console.log('6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限')
}
const options = this.options
btFindReceiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
onReceive: function (context: any, intent: any) {
plus.android.importClass(context)
plus.android.importClass(intent)
const action = intent.getAction()
if (BluetoothDevice.ACTION_FOUND == action) {
// 找到设备
const device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
const newDevice = {
name: plus.android.invoke(device, 'getName'),
address: plus.android.invoke(device, 'getAddress'),
}
options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice)
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
// 搜索完成
this.CancelDiscovery()
options.discoveryFinishedCallback && options.discoveryFinishedCallback()
}
},
})
const filter = new IntentFilter()
filter.addAction(BluetoothDevice.ACTION_FOUND)
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
activity.registerReceiver(btFindReceiver, filter)
btAdapter.startDiscovery() //开启搜索
this.state.discoveryDeviceState = true
}
/**
* 蓝牙状态监听
* @param {Activity} activity
*/
ListenBluetoothStatus() {
if (btStatusReceiver != null) {
try {
activity.unregisterReceiver(btStatusReceiver)
} catch (e) {
console.error(e)
}
btStatusReceiver = null
}
btStatusReceiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
onReceive: (context: any, intent: any) => {
plus.android.importClass(context)
plus.android.importClass(intent)
const action = intent.getAction()
const blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)
let stateStr = ''
switch (action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
switch (blueState) {
case BluetoothAdapter.STATE_TURNING_ON:
stateStr = 'STATE_TURNING_ON'
break
case BluetoothAdapter.STATE_ON:
this.state.bluetoothEnable = true
stateStr = 'STATE_ON'
break
case BluetoothAdapter.STATE_TURNING_OFF:
stateStr = 'STATE_TURNING_OFF'
break
case BluetoothAdapter.STATE_OFF:
stateStr = 'STATE_OFF'
this.state.bluetoothEnable = false
break
}
this.state.bluetoothState = stateStr
this.options.listenBTStatusCallback && this.options.listenBTStatusCallback(stateStr)
break
}
},
})
const filter = new IntentFilter()
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
activity.registerReceiver(btStatusReceiver, filter)
// 首次连接 状态回调
if (this.state.bluetoothEnable) {
this.options.listenBTStatusCallback && this.options.listenBTStatusCallback('STATE_ON')
}
}
/**
* 根据蓝牙地址,连接设备
* @param {Stirng} address
* @return {Boolean}
*/
ConnDevice(address: any, callback: (arg: boolean) => void) {
plus.android.importClass('java.io.InputStream')
plus.android.importClass('java.io.OutputStream')
plus.android.importClass('android.bluetooth.BluetoothSocket')
this.CancelDiscovery()
if (btSocket != null) {
this.CloseBtSocket()
}
this.state.readThreadState = false
try {
const device = invoke(btAdapter, 'getRemoteDevice', address)
btSocket = invoke(device, 'createRfcommSocketToServiceRecord', MY_UUID)
} catch (e) {
console.error(e)
this.ShortToast('连接失败,获取Socket失败!')
callback(false)
return false
}
try {
invoke(btSocket, 'connect')
this.ReadData() //读数据
this.ShortToast('连接成功')
callback(true)
} catch (e) {
console.error(e)
this.ShortToast('连接失败')
callback(false)
try {
btSocket.close()
btSocket = null
} catch (e1) {
console.error(e1)
}
return false
}
return true
}
/**
* 读取数据
* @param {Object} activity
* @param {Function} callback
* @return {Boolean}
*/
ReadData() {
if (!btSocket) {
this.ShortToast('请先连接蓝牙设备!')
return false
}
try {
btInStream = invoke(btSocket, 'getInputStream')
btOutStream = invoke(btSocket, 'getOutputStream')
console.log('ReadData - invoke', btSocket)
} catch (e) {
console.error(e)
this.ShortToast('创建输入输出流失败!')
this.CloseBtSocket()
return false
}
this.Read()
this.state.readThreadState = true
return true
}
/**
* 模拟java多线程读取数据
*/
Read() {
// console.log('Read - 模拟java多线程读取数据', btOutStream)
let setTimeCount = 0
clearInterval(setIntervalId)
setIntervalId = setInterval(() => {
setTimeCount++
if (this.state.readThreadState) {
const t = new Date().getTime()
//心跳检测
if (setTimeCount % 20 == 0) {
try {
btOutStream.write([0b00]) //这里报错
} catch (e) {
this.state.readThreadState = false
this.options.connExceptionCallback && this.options.connExceptionCallback(e)
}
}
const dataArr = []
while (invoke(btInStream, 'available') !== 0) {
const data = invoke(btInStream, 'read')
dataArr.push(data)
const ct = new Date().getTime()
if (ct - t > 20) {
break
}
}
if (dataArr.length > 0) {
this.options.readDataCallback && this.options.readDataCallback(dataArr)
}
}
}, 40)
}
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
DisConnDevice() {
if (btSocket != null) {
this.CloseBtSocket()
}
this.state.readThreadState = false
this.ShortToast('断开连接成功')
}
/**
* 发送数据
* @param {String} dataStr
* @return {Boolean}
*/
SendData(dataStr: string): boolean {
if (!btOutStream) {
this.ShortToast('创建输出流失败!')
return false
}
const bytes = invoke(dataStr as any, 'getBytes', 'gbk')
try {
btOutStream.write(bytes)
} catch (e) {
return false
}
return true
}
SendByteData(byteData: any) {
if (!btOutStream) {
this.ShortToast('创建输出流失败!')
return
}
try {
btOutStream.write(byteData)
} catch (e) {
return false
}
return true
}
}
使用嘛,就直接引入实例化就可以啦,不过由于蓝牙一直开着会很耗电,影响性能,如果连接上了,记得关闭蓝牙搜索功能