mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Implement API to scan multiple services in iOS
PiperOrigin-RevId: 736557350
This commit is contained in:
committed by
Copybara-Service
parent
5eab533260
commit
c20cb39f60
@@ -135,6 +135,21 @@ typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable c
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:(nullable GNCStartScanningCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* Scans for peripherals that are advertising by one of the specified services.
|
||||
*
|
||||
* @param serviceUUIDs The service UUIDs to scan for. If multiple services are specified, the
|
||||
* advertisementFoundHandler will be called for each service that is
|
||||
* discovered.
|
||||
* @param advertisementFoundHandler Called on a private queue when a peripheral has been discovered.
|
||||
* @param completionHandler Called on a private queue with @c nil if successfully started scanning
|
||||
* or an error if one has occured.
|
||||
*/
|
||||
- (void)startScanningForMultipleServices:(NSArray<CBUUID *> *)serviceUUIDs
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:
|
||||
(nullable GNCStartScanningCompletionHandler)completionHandler;
|
||||
|
||||
/**
|
||||
* Stops scanning for peripherals.
|
||||
*
|
||||
|
||||
@@ -43,8 +43,8 @@ static NSError *AlreadyScanningError() {
|
||||
// The active GATT server, or @nil if one hasn't been started yet.
|
||||
GNCBLEGATTServer *_server;
|
||||
|
||||
// The service that is being actively scanned for, or @c nil if not currently scanning.
|
||||
CBUUID *_serviceUUID;
|
||||
// The services that is being actively scanned for.
|
||||
NSMutableArray<CBUUID *> *_scanningServiceUUIDs;
|
||||
|
||||
// The handler called when an advertisement for the service represented by @c _serviceUUID has
|
||||
// been discovered. This will be called continuously, until the peripheral disappears.
|
||||
@@ -80,6 +80,7 @@ static NSError *AlreadyScanningError() {
|
||||
_centralManager.centralDelegate = self;
|
||||
_connectionCompletionHandlers = [NSMutableDictionary dictionary];
|
||||
_disconnectionHandlers = [NSMutableDictionary dictionary];
|
||||
_scanningServiceUUIDs = [NSMutableArray array];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -118,15 +119,24 @@ static NSError *AlreadyScanningError() {
|
||||
- (void)startScanningForService:(CBUUID *)serviceUUID
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:(nullable GNCStartScanningCompletionHandler)completionHandler {
|
||||
[self startScanningForMultipleServices:@[ serviceUUID ]
|
||||
advertisementFoundHandler:advertisementFoundHandler
|
||||
completionHandler:completionHandler];
|
||||
}
|
||||
|
||||
- (void)startScanningForMultipleServices:(NSArray<CBUUID *> *)serviceUUIDs
|
||||
advertisementFoundHandler:(GNCAdvertisementFoundHandler)advertisementFoundHandler
|
||||
completionHandler:
|
||||
(nullable GNCStartScanningCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
if (_serviceUUID) {
|
||||
if (_scanningServiceUUIDs.count > 0) {
|
||||
if (completionHandler) {
|
||||
completionHandler(AlreadyScanningError());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_serviceUUID = serviceUUID;
|
||||
[_scanningServiceUUIDs addObjectsFromArray:serviceUUIDs];
|
||||
_advertisementFoundHandler = advertisementFoundHandler;
|
||||
|
||||
[self internalStartScanningIfPoweredOn];
|
||||
@@ -139,7 +149,7 @@ static NSError *AlreadyScanningError() {
|
||||
- (void)stopScanningWithCompletionHandler:
|
||||
(nullable GNCStopScanningCompletionHandler)completionHandler {
|
||||
dispatch_async(_queue, ^{
|
||||
_serviceUUID = nil;
|
||||
[_scanningServiceUUIDs removeAllObjects];
|
||||
_advertisementFoundHandler = nil;
|
||||
[_centralManager stopScan];
|
||||
if (completionHandler) {
|
||||
@@ -179,11 +189,11 @@ static NSError *AlreadyScanningError() {
|
||||
// then back on. This will be called anytime the central manager's state changes, so
|
||||
// @c scanForPeripheralsWithServices:options: will be called anytime state transitions back to
|
||||
// powered on.
|
||||
if (_centralManager.state == CBManagerStatePoweredOn && _serviceUUID != nil) {
|
||||
if (_centralManager.state == CBManagerStatePoweredOn && _scanningServiceUUIDs.count > 0) {
|
||||
// Stop scanning just in case something outside of this class is already scanning.
|
||||
[_centralManager stopScan];
|
||||
[_centralManager
|
||||
scanForPeripheralsWithServices:@[ _serviceUUID ]
|
||||
scanForPeripheralsWithServices:_scanningServiceUUIDs
|
||||
// Nearby relies on the existence of an advertisement for endpoint
|
||||
// discovery/lost events, so we must set this key to keep the stream
|
||||
// of duplicate delegate events flowing. This has adverse effect on
|
||||
@@ -214,7 +224,7 @@ static NSError *AlreadyScanningError() {
|
||||
NSData *data = [[NSData alloc] initWithBase85EncodedString:localName];
|
||||
#else
|
||||
NSData *data = [[NSData alloc] initWithWebSafeBase64EncodedString:localName];
|
||||
#endif // defined(NC_IOS_SDK)
|
||||
#endif // defined(NC_IOS_SDK)
|
||||
|
||||
// A Nearby Apple advertisement should only have a single service, so simply grab the first one if
|
||||
// it exists.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
@@ -86,6 +87,11 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
bool StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanCallback callback) override;
|
||||
|
||||
// Starts scanning on multiple services and returns whether or not it was successful.
|
||||
bool StartMultipleServicesScanning(const std::vector<Uuid> &service_uuids,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanCallback callback) override;
|
||||
|
||||
// Stops scanning.
|
||||
//
|
||||
// Returns whether or not scanning was successfully stopped.
|
||||
|
||||
@@ -205,6 +205,49 @@ bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLeve
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
bool BleMedium::StartMultipleServicesScanning(const std::vector<Uuid> &service_uuids,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanCallback callback) {
|
||||
absl::MutexLock lock(&peripherals_mutex_);
|
||||
|
||||
if (service_uuids.empty()) {
|
||||
GTMLoggerError(@"No service UUIDs provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
NSMutableArray<CBUUID *> *serviceUUIDs = [NSMutableArray arrayWithCapacity:service_uuids.size()];
|
||||
for (const Uuid &service_uuid : service_uuids) {
|
||||
[serviceUUIDs addObject:CBUUID128FromCPP(service_uuid)];
|
||||
}
|
||||
|
||||
scan_cb_ = std::move(callback);
|
||||
|
||||
// Clear the map of discovered peripherals only when we are starting a new scan. If we cleared the
|
||||
// map every time we stopped a scan, we would not be able to connect to peripherals that we
|
||||
// discovered in that scan session.
|
||||
peripherals_.clear();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUIDs[0]];
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUIDs[0] ]];
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
__block NSError *blockError = nil;
|
||||
[medium_ startScanningForMultipleServices:serviceUUIDs
|
||||
advertisementFoundHandler:^(id<GNCPeripheral> peripheral,
|
||||
NSDictionary<CBUUID *, NSData *> *serviceData) {
|
||||
HandleAdvertisementFound(peripheral, serviceData);
|
||||
}
|
||||
completionHandler:^(NSError *error) {
|
||||
if (error != nil) {
|
||||
GTMLoggerError(@"Failed to start scanning for multiple services: %@", error);
|
||||
blockError = error;
|
||||
}
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
bool BleMedium::StopScanning() {
|
||||
[socketCentralManager_ stopNoScanMode];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user