Improve Apple, Android and Windows (#40)
* Cleanup connection * Reverse search list * Bump version * Fix Android serviceUuids in scanResults * Fix typo * Improve cleanup on apple * Improve Apple reconnection and service discovery * Persist long scan result name on Windows Co-authored-by: navidecklabs <navidecklabs@users.noreply.github.com> * Update changelog --------- Co-authored-by: Rohit Sangwan <rohitsangwan647@gmail.com> Co-authored-by: navidecklabs <navidecklabs@users.noreply.github.com>
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
## 0.9.9
|
||||||
|
* Improve service discovery on Apple
|
||||||
|
* Improve reconnection on Apple
|
||||||
|
* Persist long scan result name on Windows
|
||||||
|
* Fix Android serviceUuids in scanResults
|
||||||
|
* Example app improvements
|
||||||
|
|
||||||
## 0.9.8
|
## 0.9.8
|
||||||
* Improve manufacturer data discovery on Windows
|
* Improve manufacturer data discovery on Windows
|
||||||
* Example app improvements
|
* Example app improvements
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ fun BluetoothDevice.removeBond() {
|
|||||||
try {
|
try {
|
||||||
javaClass.getMethod("removeBond").invoke(this)
|
javaClass.getMethod("removeBond").invoke(this)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Removing bond has been failed. ${e.message}")
|
Log.e(TAG, "Removing bond failed. ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -665,6 +665,15 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
|
|
||||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||||
// Log.v(TAG, "onScanResult: $result")
|
// Log.v(TAG, "onScanResult: $result")
|
||||||
|
var serviceUuids: Array<String> = arrayOf<String>()
|
||||||
|
result.device.uuids?.forEach {
|
||||||
|
serviceUuids += it.uuid.toString()
|
||||||
|
}
|
||||||
|
result.scanRecord?.serviceUuids?.forEach {
|
||||||
|
if (!serviceUuids.contains(it.uuid.toString())) {
|
||||||
|
serviceUuids += it.uuid.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
mainThreadHandler?.post {
|
mainThreadHandler?.post {
|
||||||
callbackChannel?.onScanResult(
|
callbackChannel?.onScanResult(
|
||||||
UniversalBleScanResult(
|
UniversalBleScanResult(
|
||||||
@@ -673,13 +682,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
isPaired = result.device.bondState == BOND_BONDED,
|
isPaired = result.device.bondState == BOND_BONDED,
|
||||||
manufacturerDataHead = result.manufacturerDataHead,
|
manufacturerDataHead = result.manufacturerDataHead,
|
||||||
rssi = result.rssi.toLong(),
|
rssi = result.rssi.toLong(),
|
||||||
services = result.device.uuids?.map { it.uuid?.toString() ?: "" }
|
services = serviceUuids.toList()
|
||||||
?: emptyList()
|
|
||||||
)
|
)
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
|
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
|
||||||
Log.v(TAG, "onBatchScanResults: $results")
|
Log.v(TAG, "onBatchScanResults: $results")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,24 +95,51 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
func cleanUpConnection(deviceId: String) {
|
func cleanUpConnection(deviceId: String) {
|
||||||
characteristicReadFutures.removeAll { future in
|
characteristicReadFutures.removeAll { future in
|
||||||
future.deviceId == deviceId
|
if future.deviceId == deviceId {
|
||||||
|
future.result(
|
||||||
|
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
discoverServicesFutures.removeAll { future in
|
discoverServicesFutures.removeAll { future in
|
||||||
future.deviceId == deviceId
|
if future.deviceId == deviceId {
|
||||||
|
future.result(
|
||||||
|
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
discoveredServicesProgressMap[deviceId] = nil
|
discoveredServicesProgressMap[deviceId] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) {
|
func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) {
|
||||||
guard let peripheral = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(Result.failure(
|
completion(
|
||||||
FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if discoveredServicesProgressMap[deviceId] != nil {
|
if discoveredServicesProgressMap[deviceId] != nil {
|
||||||
completion(Result.failure(FlutterError(code: "AlreadyInProgress", message: "Services discovery already in progress for :\(deviceId)", details: nil)))
|
print("Services discovery already in progress for :\(deviceId), waiting for completion.")
|
||||||
|
discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let cachedServices = peripheral.services {
|
||||||
|
// If services already discovered no need to discover again
|
||||||
|
if !cachedServices.isEmpty {
|
||||||
|
// print("Services already cached for this peripheral")
|
||||||
|
discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion))
|
||||||
|
self.peripheral(peripheral, didDiscoverServices: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
peripheral.discoverServices(nil)
|
peripheral.discoverServices(nil)
|
||||||
discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion))
|
discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion))
|
||||||
}
|
}
|
||||||
@@ -270,6 +297,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
||||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, state: BlueConnectionState.disconnected.rawValue) { _ in }
|
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, state: BlueConnectionState.disconnected.rawValue) { _ in }
|
||||||
|
// Cleanup on disconnect
|
||||||
|
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) {
|
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) {
|
||||||
@@ -280,6 +309,12 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
discoveredServicesProgressMap[deviceId] = services.map { UniversalBleService(uuid: $0.uuid.uuidString, characteristics: nil) }
|
discoveredServicesProgressMap[deviceId] = services.map { UniversalBleService(uuid: $0.uuid.uuidString, characteristics: nil) }
|
||||||
for service in services {
|
for service in services {
|
||||||
|
if let cachedChar = service.characteristics {
|
||||||
|
if !cachedChar.isEmpty {
|
||||||
|
self.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: nil)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
peripheral.discoverCharacteristics(nil, for: service)
|
peripheral.discoverCharacteristics(nil, for: service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,7 +338,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||||
print("peripheral:didWriteValueForCharacteristic \(characteristic.uuid.uuidStr) error: \(String(describing: error))")
|
// print("peripheral:didWriteValueForCharacteristic \(characteristic.uuid.uuidStr) error: \(String(describing: error))")
|
||||||
// Update futures for writeValue
|
// Update futures for writeValue
|
||||||
characteristicWriteFutures.removeAll { future in
|
characteristicWriteFutures.removeAll { future in
|
||||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ class _MyAppState extends State<MyApp> {
|
|||||||
itemCount: _scanResults.length,
|
itemCount: _scanResults.length,
|
||||||
separatorBuilder: (context, index) => const Divider(),
|
separatorBuilder: (context, index) => const Divider(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
BleScanResult scanResult = _scanResults[index];
|
BleScanResult scanResult =
|
||||||
|
_scanResults[_scanResults.length - index - 1];
|
||||||
return ScannedItemWidget(
|
return ScannedItemWidget(
|
||||||
scanResult: scanResult,
|
scanResult: scanResult,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ SPEC CHECKSUMS:
|
|||||||
|
|
||||||
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
|
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
|
||||||
|
|
||||||
COCOAPODS: 1.14.3
|
COCOAPODS: 1.15.2
|
||||||
|
|||||||
@@ -259,7 +259,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0920;
|
LastSwiftUpdateCheck = 0920;
|
||||||
LastUpgradeCheck = 1430;
|
LastUpgradeCheck = 1510;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
331C80D4294CF70F00263BE5 = {
|
331C80D4294CF70F00263BE5 = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1430"
|
LastUpgradeVersion = "1510"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: universal_ble
|
name: universal_ble
|
||||||
description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
|
description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
|
||||||
version: 0.9.8
|
version: 0.9.9
|
||||||
homepage: https://navideck.com
|
homepage: https://navideck.com
|
||||||
repository: https://github.com/Navideck/universal_ble
|
repository: https://github.com/Navideck/universal_ble
|
||||||
issue_tracker: https://github.com/Navideck/universal_ble/issues
|
issue_tracker: https://github.com/Navideck/universal_ble/issues
|
||||||
|
|||||||
@@ -554,26 +554,37 @@ namespace universal_ble
|
|||||||
auto it = scanResults.find(scanResult.device_id());
|
auto it = scanResults.find(scanResult.device_id());
|
||||||
if (it != scanResults.end())
|
if (it != scanResults.end())
|
||||||
{
|
{
|
||||||
UniversalBleScanResult &existingScanResult = it->second;
|
UniversalBleScanResult ¤tScanResult = it->second;
|
||||||
bool shouldUpdate = false;
|
bool shouldUpdate = false;
|
||||||
if ((scanResult.name() == nullptr || scanResult.name()->empty()) && (existingScanResult.name() != nullptr && !existingScanResult.name()->empty()))
|
|
||||||
|
// Check if current scanResult name is longer than the received scanResult name
|
||||||
|
if (scanResult.name() != nullptr && !scanResult.name()->empty() && currentScanResult.name() != nullptr && !currentScanResult.name()->empty())
|
||||||
{
|
{
|
||||||
scanResult.set_name(*existingScanResult.name());
|
if (currentScanResult.name()->size() > scanResult.name()->size())
|
||||||
|
{
|
||||||
|
scanResult.set_name(*currentScanResult.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((scanResult.name() == nullptr || scanResult.name()->empty()) && (currentScanResult.name() != nullptr && !currentScanResult.name()->empty()))
|
||||||
|
{
|
||||||
|
scanResult.set_name(*currentScanResult.name());
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
if (scanResult.is_paired() == nullptr && existingScanResult.is_paired() != nullptr)
|
|
||||||
|
if (scanResult.is_paired() == nullptr && currentScanResult.is_paired() != nullptr)
|
||||||
{
|
{
|
||||||
scanResult.set_is_paired(existingScanResult.is_paired());
|
scanResult.set_is_paired(currentScanResult.is_paired());
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
if (scanResult.manufacturer_data_head() == nullptr && existingScanResult.manufacturer_data_head() != nullptr)
|
if (scanResult.manufacturer_data_head() == nullptr && currentScanResult.manufacturer_data_head() != nullptr)
|
||||||
{
|
{
|
||||||
scanResult.set_manufacturer_data_head(existingScanResult.manufacturer_data_head());
|
scanResult.set_manufacturer_data_head(currentScanResult.manufacturer_data_head());
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
if (scanResult.services() == nullptr && existingScanResult.services() != nullptr)
|
if (scanResult.services() == nullptr && currentScanResult.services() != nullptr)
|
||||||
{
|
{
|
||||||
scanResult.set_services(existingScanResult.services());
|
scanResult.set_services(currentScanResult.services());
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,8 +592,8 @@ namespace universal_ble
|
|||||||
if (!shouldUpdate)
|
if (!shouldUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// update the existing scan result
|
// update the current scan result
|
||||||
existingScanResult = scanResult;
|
currentScanResult = scanResult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user