关于硬件设备的蓝牙连接一般都有给的demo,一般情况下按照demo去写就可以了,但是实际情况下,
有时候,实际应用,要比demo要复杂一些,比如设备使用过程中,直接就断开,断电等异常情况比较多.
我看网上处理蓝牙操作,有主动连接硬件设备的,这样的连接方式应该稳定一些,因为我这边用,蓝牙扫描的方式,实现了
所以我就没有再去改代码,看了一下网上的代码,也没有太难,记录一下自己的实现方式,以后可以复制粘贴使用.
实现方式:蓝牙要先开启,然后,程序去扫描附近蓝牙设备,如果找到的蓝牙设备中,发现有和自己提前设置的mac地址
一样的就主动去连接这个设备,就相当于找到这个设备了,然后就可以去操作设备了.
android中使用蓝牙的时候,需要引入蓝牙使用权限:
需要在AndroidManifest.xml 文件中添加蓝牙权限
<!--蓝牙权限-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
然后,如果对接的硬件,还需要其他权限,会有说明文档,也需要添加上
然后需要定义些,蓝牙需要的变量
0.定义蓝牙相关变量
private String mac_address="";
private BluetoothAdapter bluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private BluetoothGattService bluetoothGattService;
private BluetoothGattCharacteristic writeCharacteristic;
private BluetoothGattCharacteristic notifyCharacteristic;
private ReentrantLock commLock =new ReentrantLock();
private BluetoothDevice currentDevice;
1.然后,去初始化蓝牙,这个在onCreate方法中调用,就可以了.
private void lk_xyj_initBloodPressure() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "说明此设备不支持蓝牙操作", Toast.LENGTH_LONG).show();
return;
}
}
2.然后再去,搜索设备

//1.搜索乐康血压计
private void lk_xyj_searchDevice() {
// 注册Receiver来获取蓝牙设备相关的结果
IntentFilter intent = new IntentFilter("android.bluetooth.device.action.UUID");
intent.addAction(BluetoothDevice.ACTION_FOUND); // 用BroadcastReceiver来取得搜索结果
intent.addAction(BluetoothDevice.EXTRA_UUID);
intent.addAction(BluetoothDevice.ACTION_UUID);
intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intent.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(lk_xyj_searchDevices, intent);
bluetoothAdapter.startDiscovery();
BaseApplication.context().showDialog(FaceBodyCheckActivity.this, "正在连接设备...");
}
可以看到上面,注册了一个广播接收器,来接收蓝牙的信息
注册完蓝牙广播接收器,以后然后bluetoothAdapter,startDiscovery() 这个是开启蓝牙扫描
3.然后看到蓝牙扫描中
//2.乐康血压计搜索,广播类
private BroadcastReceiver lk_xyj_searchDevices = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_FOUND)) { //found device
currentDevice = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// BluetoothDevice device = intent
// .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mac_address.equals(currentDevice.getAddress())) {
bluetoothAdapter.cancelDiscovery();
mBluetoothGatt = currentDevice.connectGatt(FaceBodyCheckActivity.this, false, lk_xyj_GattCallback);
}
} else if (BluetoothDevice.ACTION_UUID.equals(action)) {
currentDevice = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// BluetoothDevice device = intent
// .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mac_address.equals(currentDevice.getAddress())) {
bluetoothAdapter.cancelDiscovery();
mBluetoothGatt = currentDevice.connectGatt(FaceBodyCheckActivity.this, false, lk_xyj_GattCallback);
}
}
}
};
这个方法,是只要收到蓝牙的广播信息就走这个方法,并且,会把当前扫描的蓝牙设备赋值给currentDevice 然后获取currentDevice的mac地址
然后判断这个扫描到的设备的mac和我们要连接的设备的mac是否一样,如果一样,就取消bluetoothAdapter.cancelDiscovery() 取消蓝牙继续扫描
然后,去连接这个设备currentDevice.connectGatt(FaceBodyCheckActivity.this,false,lk_xyj_GattCallback);
这个是去连接,扫描到的这个蓝牙设备,连接以后,去回调,lk_xyj_GattCallback这个对象.
4.然后连接设备以后的回调
//3.乐康血压计,handler类
Handler lk_xyj_mainHandler = new Handler();
private BluetoothGattCallback lk_xyj_GattCallback = new BluetoothGattCallback() {
// 这里有9个要实现的方法,看情况要实现那些,用到那些就实现那些
//当连接状态发生改变的时候
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) {
mBluetoothGatt.discoverServices();
lk_xyj_mainHandler.post(new Runnable() {
@Override
public void run() {
if (newState == BluetoothProfile.STATE_CONNECTED) {
BaseApplication.context().closeDialog();
ToastUtils.toast(FaceBodyCheckActivity.this,"设备启动成功");
} else {
Toast.makeText(FaceBodyCheckActivity.this, "设备连接已断开", Toast.LENGTH_SHORT).show();
}
}
});
};
//回调响应特征写操作的结果。
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.out.println(222222);
}
;
//回调响应特征读操作的结果。
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.out.println(3333333);
}
//当服务被发现的时候回调的结果
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
try {
//设置serviceUUID,原型是:BluetoothGattService bluetoothGattService = bluetoothGatt.getService(UUID.fromString(SERVICESUUID));
bluetoothGattService = mBluetoothGatt.getService(UUID.fromString(DeviceFinal.LK_XYJ_SERVICESUUID));
//设置写入特征UUID,原型是:BluetoothGattCharacteristic writeCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(WRITEUUID));
writeCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(DeviceFinal.LK_XYJ_WRITEUUID));
//设置监听特征UUID,原型是:BluetoothGattCharacteristic notifyCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(NOTIFYUUID));
notifyCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(DeviceFinal.LK_XYJ_NOTIFYUUID));
//开启监听
boolean re = gatt.setCharacteristicNotification(notifyCharacteristic, true);
System.out.println(re);
} catch (Exception e) {
e.printStackTrace();
lk_xyj_mainHandler.post(new Runnable() {
@Override
public void run() {
ToastUtils.toast(FaceBodyCheckActivity.this,"所选设备不是血压计,请确认后再试!");
// xyj_start.setVisibility(View.GONE);
// xyj_sub.setVisibility(View.GONE);
// lk_xyj_msg.setText("所选设备不是血压计,请确认后再试!");
}
});
}
}
//接受数据回调
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue();
final String str = lk_xyj_bytesToHex(value);
System.out.println(lk_xyj_bytesToHex(value));
lk_xyj_mainHandler.post(new Runnable() {
@Override
public void run() {
if (str.indexOf("0240dd0200") != -1) {
BigInteger amount = new BigInteger(String.valueOf(str.charAt(10)) + String.valueOf(str.charAt(11)), 16);
// lk_xyj_msg.setText(amount + "");
lk_xyj_subTempData(amount.intValue());
} else if (str.indexOf("0240dd0c") != -1) {
String sb = String.valueOf(str.charAt(12)) + String.valueOf(str.charAt(13));
String db = String.valueOf(str.charAt(16)) + String.valueOf(str.charAt(17));
String pr = String.valueOf(str.charAt(24)) + String.valueOf(str.charAt(25));
BigInteger SBPvalue = new BigInteger(sb, 16);
BigInteger DBPvalue = new BigInteger(db, 16);
BigInteger PRPvalue = new BigInteger(pr, 16);
if (!sb.equals("ff")) {
lk_xyj_spvalue=SBPvalue + "";
lk_xyj_dpvalue=DBPvalue + "";
lk_xyj_prvalue=PRPvalue + "";
// lk_xyj_sp.setText(SBPvalue + "");
// lk_xyj_dp.setText(DBPvalue + "");
// lk_xyj_pr.setText(PRPvalue + "");
//xyj_sub.setVisibility(View.VISIBLE);
//发送血压数据
lk_xyj_subData();
} else {
String err = String.valueOf(str.charAt(24)) + String.valueOf(str.charAt(25));
String errStr = "";
switch (new BigInteger(err, 16).intValue()) {
case 1:
errStr = "传感器震荡异常";
break;
case 2:
errStr = "检测不到足够的心跳或算不出血压";
break;
case 3:
errStr = "测量结果异常";
break;
case 4:
errStr = "袖带过松或漏气(10 秒内加压不到 30mmHg)";
break;
case 5:
errStr = "气管被堵住";
break;
case 6:
errStr = "测量时压力波动大";
break;
case 7:
errStr = "压力超过上限";
break;
case 8:
errStr = "标定数据异常或未标定";
break;
default:
errStr = "血压计异常";
}
Toast.makeText(FaceBodyCheckActivity.this, errStr, Toast.LENGTH_LONG).show();
Toast.makeText(FaceBodyCheckActivity.this, "请重新测量", Toast.LENGTH_LONG).show();
// lk_xyj_msg.setText(errStr);
}
}
}
});
// System.out.println("ReceiveSuccess" + new BytesHexStrTranslate().bytesToHexFun1(value));
}
//当连接能被被读的操作
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
System.out.println(555555);
}
};
可以看到上面回调函数就可以判断设备连接成功还是连接失败.
并且连接成功以后,如果收到蓝牙的测量数据会回调对应的方法.








