diff options
author | Timur Pocheptsov <timur.pocheptsov@theqtcompany.com> | 2015-10-28 14:28:10 +0100 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@theqtcompany.com> | 2015-10-29 11:49:04 +0000 |
commit | e6600461432790ac2f1111df734951ff472e8161 (patch) | |
tree | f90ef71c2cc573ba8ae51c73daeaf0f2e26907c3 /src/bluetooth/osx/osxbtledeviceinquiry.mm | |
parent | 823dd31ac10dea02b1cc4baf79a2761b95c5f63f (diff) |
Core Bluetooth - give a user the second chance to enable Bluetooth
On iOS when we receive centralManagerDidUpdateState with the state
== PoweredOff, iOS also shows an alert on screen, asking to enable
Bluetooth via the "Settings" app. If we do not report an error and
a user indeed enables BT, we can continue to work.
Change-Id: Ic1f63f205b56fc356bc7fa645359b583c00195a6
Task-number: QTBUG-48713
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/osx/osxbtledeviceinquiry.mm')
-rw-r--r-- | src/bluetooth/osx/osxbtledeviceinquiry.mm | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm index c46c68fc..86ef651e 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm @@ -110,6 +110,7 @@ using namespace QT_NAMESPACE; @interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) (PrivateAPI) <CBCentralManagerDelegate, CBPeripheralDelegate> // "Timeout" callback to stop a scan. - (void)stopScan; +- (void)handlePoweredOffAfterDelay; @end @implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) @@ -169,6 +170,27 @@ using namespace QT_NAMESPACE; delegate->LEdeviceInquiryFinished(); } +- (void)handlePoweredOffAfterDelay +{ + // If we are here, this means: + // we received 'PoweredOff' while pendingStart == true + // and no 'PoweredOn' after this. + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + Q_ASSERT_X(pendingStart, Q_FUNC_INFO, "invalid state"); + + pendingStart = false; + if (cancelled) { + // Timeout happened before + // the second status update, but after 'stop'. + delegate->LEdeviceInquiryFinished(); + } else { + // Timeout and not 'stop' between 'start' + // and 'DidUpdateStatus': + delegate->LEnotSupported(); + } +} + - (bool)start { Q_ASSERT_X(![self isActive], Q_FUNC_INFO, "LE device scan is already active"); @@ -204,6 +226,17 @@ using namespace QT_NAMESPACE; { Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + const CBCentralManagerState state = central.state; + + if (pendingStart && (state == CBCentralManagerStatePoweredOn + || state == CBCentralManagerStateUnsupported + || state == CBCentralManagerStateUnauthorized + || state == CBCentralManagerStatePoweredOff)) { + // We probably had 'PoweredOff' before, + // cancel the previous handlePoweredOffAfterDelay. + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + } + if (cancelled) { Q_ASSERT_X(!isActive, Q_FUNC_INFO, "isActive is true"); pendingStart = false; @@ -211,7 +244,6 @@ using namespace QT_NAMESPACE; return; } - const CBCentralManagerState state = central.state; if (state == CBCentralManagerStatePoweredOn) { if (pendingStart) { pendingStart = false; @@ -229,22 +261,28 @@ using namespace QT_NAMESPACE; pendingStart = false; delegate->LEnotSupported(); } else if (isActive) { - // It's not clear if this thing can happen at all. - // We had LE supported and now .. not anymore? - // Report as an error. + // Cancel stopScan: [NSObject cancelPreviousPerformRequestsWithTarget:self]; + isActive = false; [manager stopScan]; delegate->LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); } } else if (state == CBCentralManagerStatePoweredOff) { if (pendingStart) { +#ifndef Q_OS_OSX + // On iOS a user can see at this point an alert asking to enable + // Bluetooth in the "Settings" app. If a user does, + // we'll receive 'PoweredOn' state update later. + [self performSelector:@selector(handlePoweredOffAfterDelay) withObject:nil afterDelay:30.]; + return; +#endif pendingStart = false; delegate->LEnotSupported(); } else if (isActive) { - // We were able to start (isActive == true), so we had - // powered ON and now the adapter is OFF. + // Cancel stopScan: [NSObject cancelPreviousPerformRequestsWithTarget:self]; + isActive = false; [manager stopScan]; delegate->LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); @@ -259,18 +297,21 @@ using namespace QT_NAMESPACE; // -CBCentralManagerStateResetting // The connection with the system service was momentarily // lost; an update is imminent. " - // - // TODO: check if "is imminent" means UpdateState will - // be called again with something more reasonable. } } - (void)stop { - [NSObject cancelPreviousPerformRequestsWithTarget:self]; + if (!pendingStart) { + // pendingStart == true means either no selector at all, + // or handlePoweredOffAfter delay and we do not want to cancel it yet, + // waiting for DidUpdateState or handlePoweredOffAfter, whoever + // fires first ... + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + } if (pendingStart || cancelled) { - // We have to wait for a status update. + // We have to wait for a status update or handlePoweredOffAfterDelay. cancelled = true; return; } |