emis-sapp/components/tpx-bluetooth-native/nativeBlueTooth.js
2024-05-31 18:42:15 +08:00

458 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* html 5+ 串口蓝牙操作
* 2021.04.23 uni-app版本
* @auth boolTrue
*/
/**
* 初始化参数
*/
//#ifdef APP-PLUS
let BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
let Intent = plus.android.importClass("android.content.Intent");
let IntentFilter = plus.android.importClass("android.content.IntentFilter");
let BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
let UUID = plus.android.importClass("java.util.UUID");
let Toast = plus.android.importClass("android.widget.Toast");
//连接串口设备的 UUID
let MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
let invoke = plus.android.invoke;
let btAdapter = BluetoothAdapter.getDefaultAdapter();
let activity = plus.android.runtimeMainActivity();
let btSocket = null;
let btInStream = null;
let btOutStream = null;
let setIntervalId = 0;
let btFindReceiver = null; //蓝牙搜索广播接收器
let btStatusReceiver = null; //蓝牙状态监听广播
//#endif
/**
* 构造对象
*/
var blueToothTool = {
state : {
bluetoothEnable: false, //蓝牙是否开启
bluetoothState: "", //当前蓝牙状态
discoveryDeviceState: false, //是否正在搜索蓝牙设备
readThreadState: false, //数据读取线程状态
},
options : {
/**
* 监听蓝牙状态回调
* @param {String} state
*/
listenBTStatusCallback: function(state) {},
/**
* 搜索到新的蓝牙设备回调
* @param {Device} newDevice
*/
discoveryDeviceCallback: function(newDevice) {},
/**
* 蓝牙搜索完成回调
*/
discoveryFinishedCallback: function() {},
/**
* 接收到数据回调
* @param {Array} dataByteArr
*/
readDataCallback: function(dataByteArr) {},
/**
* 蓝牙连接中断回调
* @param {Exception} e
*/
connExceptionCallback: function(e) {}
},
init(setOptions) {
Object.assign(this.options, setOptions);
this.state.bluetoothEnable = this.getBluetoothStatus();
this.listenBluetoothStatus();
},
shortToast(msg) {
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 activity
* @param requestCode
*/
turnOnBluetooth() {
if(btAdapter == null) {
shortToast("没有蓝牙");
return;
}
if(!btAdapter.isEnabled()) {
if(activity == null) {
shortToast("未获取到activity");
return;
} else {
let intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
let requestCode = 1;
activity.startActivityForResult(intent, requestCode);
return;
}
} else {
shortToast("蓝牙已经打开");
}
},
/**
* 关闭蓝牙
*/
turnOffBluetooth() {
if(btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable();
}
if(btFindReceiver != null) {
try {
activity.unregisterReceiver(btFindReceiver);
} catch(e) {
console.log("turnOffBluetooth error=========", e)
}
btFindReceiver = null;
}
this.state.bluetoothEnable = false;
this.cancelDiscovery();
closeBtSocket();
if(btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable();
shortToast("蓝牙关闭成功");
} else {
shortToast("蓝牙已经关闭");
}
},
/**
* 获取已经配对的设备
* @return {Array} connetedDevices
*/
getPairedDevices() {
let pairedDevices = [];
//蓝牙连接android原生对象,是一个set集合
let pairedDevicesAndroid = null;
if(btAdapter != null && btAdapter.isEnabled()) {
pairedDevicesAndroid = btAdapter.getBondedDevices();
} else {
shortToast("蓝牙未开启");
}
if(!pairedDevicesAndroid) {
return pairedDevices;
}
//遍历连接设备的set集合,转换为js数组
let it = invoke(pairedDevicesAndroid, "iterator");
while(invoke(it, "hasNext")) {
let 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.log("discoveryNewDevice error=========", e)
}
btFindReceiver = null;
this.cancelDiscovery();
}
let Build = plus.android.importClass("android.os.Build");
//6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
if(Build.VERSION.SDK_INT >= 6.0){
}
let options = this.options
btFindReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
"onReceive": function(context, intent) {
console.log("btFindReceiver onReceive")
plus.android.importClass(context);
plus.android.importClass(intent);
let action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND == action) { // 找到设备
let device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
let newDevice = {
"name": plus.android.invoke(device, "getName"),
"address": plus.android.invoke(device, "getAddress")
}
options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice);
}
if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) { // 搜索完成
cancelDiscovery();
options.discoveryFinishedCallback && options.discoveryFinishedCallback();
}
}
});
let filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
activity.registerReceiver(btFindReceiver, filter);
btAdapter.startDiscovery(); //开启搜索
console.log("btAdapter.startDiscovery")
this.state.discoveryDeviceState = true;
},
/**
* 蓝牙状态监听
* @param {Activity} activity
*/
listenBluetoothStatus() {
if(btStatusReceiver != null) {
try {
activity.unregisterReceiver(btStatusReceiver);
} catch(e) {
console.log("listenBluetoothStatus error=========", e)
}
btStatusReceiver = null;
}
btStatusReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
"onReceive": (context, intent)=> {
plus.android.importClass(context);
plus.android.importClass(intent);
let action = intent.getAction();
switch(action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
let blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
let stateStr = "";
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;
}
}
});
let 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, callback) {
let InputStream = plus.android.importClass("java.io.InputStream");
let OutputStream = plus.android.importClass("java.io.OutputStream");
let BluetoothSocket = plus.android.importClass("android.bluetooth.BluetoothSocket");
this.cancelDiscovery();
if(btSocket != null) {
this.closeBtSocket();
}
this.state.readThreadState = false;
try {
let device = invoke(btAdapter, "getRemoteDevice", address);
btSocket = invoke(device, "createRfcommSocketToServiceRecord", MY_UUID);
} catch(e) {
console.error("连接失败,获取Socket失败!", e);
shortToast("连接失败,获取Socket失败!");
callback(false)
return false;
}
try {
invoke(btSocket, "connect");
this.readData(); //读数据
this.shortToast("连接成功");
callback(true)
} catch(e) {
console.error("connDevice error:========!", e);
this.shortToast("连接失败");
callback(false)
try {
btSocket.close();
btSocket = null;
} catch(e1) {
console.error("btSocket.close error:========!", e1);
}
return false;
}
return true;
},
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
disConnDevice() {
if(btSocket != null) {
this.closeBtSocket();
}
this.state.readThreadState = false;
this.shortToast("断开连接成功");
},
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
closeBtSocket() {
this.state.readThreadState = false;
if(!btSocket) {
return;
}
try {
btSocket.close();
} catch(e) {
console.log("closeBtSocket error=========", e)
btSocket = null;
}
},
/**
* 取消发现
*/
cancelDiscovery() {
if(btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
if(btFindReceiver != null) {
activity.unregisterReceiver(btFindReceiver);
btFindReceiver = null;
}
this.state.discoveryDeviceState = false;
},
/**
* 读取数据
* @param {Object} activity
* @param {Function} callback
* @return {Boolean}
*/
readData() {
if(!btSocket) {
this.shortToast("请先连接蓝牙设备!");
return false;
}
try {
btInStream = invoke(btSocket, "getInputStream");
btOutStream = invoke(btSocket, "getOutputStream");
} catch(e) {
console.error("readData error:========!", e);
this.shortToast("创建输入输出流失败!");
this.closeBtSocket();
return false;
}
this.read();
this.state.readThreadState = true;
return true;
},
/**
* 模拟java多线程读取数据
*/
read() {
let setTimeCount = 0;
clearInterval(setIntervalId);
setIntervalId = setInterval(()=> {
setTimeCount++;
if(this.state.readThreadState) {
let t = new Date().getTime();
//心跳检测
if(setTimeCount % 20 == 0) {
try {
btOutStream.write([0b00]);
} catch(e) {
console.log("===connExceptionCallback===", e)
this.state.readThreadState = false;
this.options.connExceptionCallback && this.options.connExceptionCallback(e);
}
}
let dataArr = [];
while(invoke(btInStream, "available") !== 0) {
let data = invoke(btInStream, "read");
dataArr.push(data);
let ct = new Date().getTime();
if(ct - t > 20) {
break;
}
}
if(dataArr.length > 0) {
this.options.readDataCallback && this.options.readDataCallback(dataArr);
}
}
}, 40);
},
/**
* 发送数据
* @param {String} dataStr
* @return {Boolean}
*/
sendData(dataStr) {
if(!btOutStream) {
this.shortToast("创建输出流失败!");
return;
}
let bytes = invoke(dataStr, 'getBytes', 'gbk');
try {
btOutStream.write(bytes);
} catch(e) {
console.log("sendData error=========", e)
return false;
}
return true;
},
sendByteData(byteData) {
if(!btOutStream) {
this.shortToast("创建输出流失败!");
return;
}
try {
console.log("====byteData====", byteData)
btOutStream.write(byteData);
} catch(e) {
console.log("sendByteData error=========", e)
return false;
}
return true;
}
}
export default blueToothTool