自动连接到 BLE 设备 [Android]
Automatic connecting to a BLE device [Android]
我正在开发一个 Android 应用程序,它应该自动连接到具有指定 MAC 地址的 BLE 设备。
基本上扫描应该是 运行 24/7,一旦发现设备,服务就应该连接到它,最好停止扫描。
我设法做到了以下几点:
public void startBluetoothScan() {
if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (!scanning) {
service.startScan();
}
}
}
这是整体方法:
private void configBluetooth() {
BluetoothConfiguration config = new BluetoothConfiguration();
config.context = getApplicationContext();
config.bluetoothServiceClass = BluetoothLeService.class; // BluetoothClassicService.class or BluetoothLeService.class
config.bufferSize = 1024;
config.characterDelimiter = '\n';
config.deviceName = "Your App Name";
config.callListenersInMainThread = true;
// Bluetooth Classic
config.uuid = null; // Set null to find all devices on scan.
// Bluetooth LE
config.uuidService = UUID_HRS;
config.uuidCharacteristic = UUID_HRD;
config.transport = BluetoothDevice.TRANSPORT_LE; // Only for dual-mode devices
BluetoothLeService.init(config);
service = (BluetoothLeService) BluetoothLeService.getDefaultInstance();
service.setOnScanCallback(new BluetoothLeService.OnBluetoothScanCallback() {
@Override
public void onDeviceDiscovered(BluetoothDevice device, int rssi) {
Log.d("Found device address", device.getAddress());
if (device.getAddress().equals(UserHRMAddress)){
if (!deviceList.contains(device)) {
Log.d("Connecting to", device.getAddress());
connectDevice(device);
deviceList.add(device);
}
}
}
@Override
public void onStartScan() {
Log.d("Started Scan", "now");
scanning = true;
}
@Override
public void onStopScan() {
Log.d("Stopped Scan", "now");
scanning = false;
startBluetoothScan();
}
});
service.startScan();
}
上面的方法是 this 库的使用,它应该使 BLE 更容易(我尝试过它并且同样不喜欢它)基本上扫描 returns 相同的设备大约一千次几秒钟,而没有机会先连接到它。有没有可能让每个设备在扫描时只被发现一次?有没有更合适的方法来实现自动连接的 24/7 搜索?
我还发现,BluetoothGattCallback onConnectionStateChange 方法执行例如当您关闭 BLE 设备或进入飞行模式时不会被调用。如果那样做,我的生活就会轻松很多。
我的 BluetoothGattCallback 方法的相关部分如下所示:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d("onConnectionStateChange", gatt.getDevice().getName());
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d("Status", "success");
heartRateService = gatt.getService(UUID_HRS);
batteryLevelService = gatt.getService(Battery_Service_UUID);
if (batteryLevelService != null) {
batteryLevelCharacteristic =
batteryLevelService.getCharacteristic(Battery_Level_UUID);
}
if (heartRateService != null) {
heartRateCharacteristic = heartRateService.getCharacteristic(UUID_HRD);
boolean res = gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER);
gatt.setCharacteristicNotification(heartRateCharacteristic, true);
try {
BluetoothGattDescriptor descriptor = heartRateCharacteristic.getDescriptor(
UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
} catch (Exception ex) {
Log.e(TAG, "wuuuuut?");
}
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
只需将 connectGatt 与 autoConnect = true 一起使用。这适用于所有 Android 版本,并且与 Nougat 中引入的扫描相比,没有使用限制。这样做会告诉蓝牙控制器在检测到广告后立即连接到设备。请注意,由于 android api 很遗憾在连接到特定 BD 地址时缺少 "address type" 参数,您要么需要与设备绑定,要么必须通过某些蓝牙扫描发现它,因为蓝牙是上次打开的。
不幸的是,当蓝牙打开时,您仍然需要蓝牙状态更改广播接收器来重新启动所有内容。
我正在开发一个 Android 应用程序,它应该自动连接到具有指定 MAC 地址的 BLE 设备。 基本上扫描应该是 运行 24/7,一旦发现设备,服务就应该连接到它,最好停止扫描。
我设法做到了以下几点:
public void startBluetoothScan() {
if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (!scanning) {
service.startScan();
}
}
}
这是整体方法:
private void configBluetooth() {
BluetoothConfiguration config = new BluetoothConfiguration();
config.context = getApplicationContext();
config.bluetoothServiceClass = BluetoothLeService.class; // BluetoothClassicService.class or BluetoothLeService.class
config.bufferSize = 1024;
config.characterDelimiter = '\n';
config.deviceName = "Your App Name";
config.callListenersInMainThread = true;
// Bluetooth Classic
config.uuid = null; // Set null to find all devices on scan.
// Bluetooth LE
config.uuidService = UUID_HRS;
config.uuidCharacteristic = UUID_HRD;
config.transport = BluetoothDevice.TRANSPORT_LE; // Only for dual-mode devices
BluetoothLeService.init(config);
service = (BluetoothLeService) BluetoothLeService.getDefaultInstance();
service.setOnScanCallback(new BluetoothLeService.OnBluetoothScanCallback() {
@Override
public void onDeviceDiscovered(BluetoothDevice device, int rssi) {
Log.d("Found device address", device.getAddress());
if (device.getAddress().equals(UserHRMAddress)){
if (!deviceList.contains(device)) {
Log.d("Connecting to", device.getAddress());
connectDevice(device);
deviceList.add(device);
}
}
}
@Override
public void onStartScan() {
Log.d("Started Scan", "now");
scanning = true;
}
@Override
public void onStopScan() {
Log.d("Stopped Scan", "now");
scanning = false;
startBluetoothScan();
}
});
service.startScan();
}
上面的方法是 this 库的使用,它应该使 BLE 更容易(我尝试过它并且同样不喜欢它)基本上扫描 returns 相同的设备大约一千次几秒钟,而没有机会先连接到它。有没有可能让每个设备在扫描时只被发现一次?有没有更合适的方法来实现自动连接的 24/7 搜索?
我还发现,BluetoothGattCallback onConnectionStateChange 方法执行例如当您关闭 BLE 设备或进入飞行模式时不会被调用。如果那样做,我的生活就会轻松很多。
我的 BluetoothGattCallback 方法的相关部分如下所示:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d("onConnectionStateChange", gatt.getDevice().getName());
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d("Status", "success");
heartRateService = gatt.getService(UUID_HRS);
batteryLevelService = gatt.getService(Battery_Service_UUID);
if (batteryLevelService != null) {
batteryLevelCharacteristic =
batteryLevelService.getCharacteristic(Battery_Level_UUID);
}
if (heartRateService != null) {
heartRateCharacteristic = heartRateService.getCharacteristic(UUID_HRD);
boolean res = gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER);
gatt.setCharacteristicNotification(heartRateCharacteristic, true);
try {
BluetoothGattDescriptor descriptor = heartRateCharacteristic.getDescriptor(
UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
} catch (Exception ex) {
Log.e(TAG, "wuuuuut?");
}
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
只需将 connectGatt 与 autoConnect = true 一起使用。这适用于所有 Android 版本,并且与 Nougat 中引入的扫描相比,没有使用限制。这样做会告诉蓝牙控制器在检测到广告后立即连接到设备。请注意,由于 android api 很遗憾在连接到特定 BD 地址时缺少 "address type" 参数,您要么需要与设备绑定,要么必须通过某些蓝牙扫描发现它,因为蓝牙是上次打开的。
不幸的是,当蓝牙打开时,您仍然需要蓝牙状态更改广播接收器来重新启动所有内容。