diff options
author | Julian Greilich <j.greilich@gmx.de> | 2023-01-26 19:19:21 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-02-03 18:32:24 +0000 |
commit | 491597cfb4529a77c4bfa57542ad169e8ec07067 (patch) | |
tree | 7a489a10a171e066785406f3bc4b105b806639e0 | |
parent | ed01eae6433a4e3d72e8aff7b9ebc862a0df7d99 (diff) |
iOS NFC: Always ensure timeout after session invalidation
iOS needs some time after invalidating a session before a new session
can be started. Otherwise the NFC dialog of iOS will not show up.
For restarting a session inside the iOS NearfieldManager, this was
already solved with a timeout of 2 seconds.
This commit fixes the case, that a user of the Nearfieldmanager
restarts a session manually too fast.
Change-Id: Ic91ad225a9cab13ba92523f33a19f44af68575a0
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 849ba86ba9a073a266219b6a39786e20f4f3ed7b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/nfc/qnearfieldmanager_ios.mm | 97 | ||||
-rw-r--r-- | src/nfc/qnearfieldmanager_ios_p.h | 5 |
2 files changed, 61 insertions, 41 deletions
diff --git a/src/nfc/qnearfieldmanager_ios.mm b/src/nfc/qnearfieldmanager_ios.mm index 3d3172db..fd9de125 100644 --- a/src/nfc/qnearfieldmanager_ios.mm +++ b/src/nfc/qnearfieldmanager_ios.mm @@ -46,6 +46,10 @@ QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() } else { qCWarning(QT_IOS_NFC, "Failed to allocate NDEF reading session's delegate"); } + + sessionTimer.setInterval(2000); + sessionTimer.setSingleShot(true); + connect(&sessionTimer, &QTimer::timeout, this, &QNearFieldManagerPrivateImpl::onSessionTimer); } QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() @@ -94,15 +98,16 @@ bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::Access case QNearFieldTarget::TagTypeSpecificAccess: if (@available(iOS 13, *)) if (NFCTagReaderSession.readingAvailable) { - detectionRunning = true; - startSession(); - activeAccessMethod = accessMethod; - return true; + detectionRunning = scheduleSession(accessMethod); + if (detectionRunning) + activeAccessMethod = accessMethod; + return detectionRunning; } return false; case QNearFieldTarget::NdefAccess: if (NFCNDEFReaderSession.readingAvailable) { - if (startNdefSession()) + detectionRunning = scheduleSession(accessMethod); + if (detectionRunning) activeAccessMethod = accessMethod; return detectionRunning; } @@ -114,44 +119,60 @@ bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::Access void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &errorMessage) { - if (detectionRunning) { - if (activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess) { - stopSession(errorMessage); - } else if (activeAccessMethod == QNearFieldTarget::NdefAccess) { - stopNdefSession(errorMessage); - } else { - qCWarning(QT_IOS_NFC, "Unknown access method, cannot stop target detection"); - return; - } + if (!detectionRunning) + return; + + isSessionScheduled = false; - detectionRunning = false; - Q_EMIT targetDetectionStopped(); + if (activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess) { + stopSession(errorMessage); + } else if (activeAccessMethod == QNearFieldTarget::NdefAccess) { + stopNdefSession(errorMessage); + } else { + qCWarning(QT_IOS_NFC, "Unknown access method, cannot stop target detection"); + return; } + + detectionRunning = false; + Q_EMIT targetDetectionStopped(); } +bool QNearFieldManagerPrivateImpl::scheduleSession(QNearFieldTarget::AccessMethod accessMethod) +{ + if (sessionTimer.isActive()) { + isSessionScheduled = true; + return true; + } + + if (accessMethod == QNearFieldTarget::TagTypeSpecificAccess) { + startSession(); + return true; + } else if (accessMethod == QNearFieldTarget::NdefAccess) { + return startNdefSession(); + } + + return false; +} void QNearFieldManagerPrivateImpl::startSession() { - if (detectionRunning) { - if (@available(iOS 13, *)) { - [delegate startSession]; - } + if (@available(iOS 13, *)) { + [delegate startSession]; } } bool QNearFieldManagerPrivateImpl::startNdefSession() { if (!ndefDelegate) - return detectionRunning = false; + return false; if (auto queue = qt_Nfc_Queue()) { - dispatch_sync(queue, ^{ - detectionRunning = [ndefDelegate startSession]; - }); - return detectionRunning; + __block bool startSessionSucceded = false; + dispatch_sync(queue, ^{ startSessionSucceded = [ndefDelegate startSession]; }); + return startSessionSucceded; } - return detectionRunning = false; + return false; } void QNearFieldManagerPrivateImpl::stopSession(const QString &error) @@ -235,25 +256,21 @@ void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivateImpl *tar void QNearFieldManagerPrivateImpl::onDidInvalidateWithError(bool doRestart) { clearTargets(); + sessionTimer.start(); - if (detectionRunning && doRestart) - { - if (!isRestarting) { - isRestarting = true; - using namespace std::chrono_literals; - QTimer::singleShot(2s, this, [this](){ - isRestarting = false; - if (activeAccessMethod == QNearFieldTarget::NdefAccess) - startNdefSession(); - else - startSession(); - }); - } + if (detectionRunning && doRestart && scheduleSession(activeAccessMethod)) return; - } detectionRunning = false; Q_EMIT targetDetectionStopped(); } +void QNearFieldManagerPrivateImpl::onSessionTimer() +{ + if (isSessionScheduled && !scheduleSession(activeAccessMethod)) { + detectionRunning = false; + Q_EMIT targetDetectionStopped(); + } +} + QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_ios_p.h b/src/nfc/qnearfieldmanager_ios_p.h index 5b38b4fe..ef638ecb 100644 --- a/src/nfc/qnearfieldmanager_ios_p.h +++ b/src/nfc/qnearfieldmanager_ios_p.h @@ -59,10 +59,12 @@ private: QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) *delegate API_AVAILABLE(ios(13.0)) = nullptr; QIosNfcNdefSessionDelegate *ndefDelegate = nullptr; bool detectionRunning = false; - bool isRestarting = false; + bool isSessionScheduled = false; + QTimer sessionTimer; QList<QNearFieldTargetPrivateImpl *> detectedTargets; QNearFieldTarget::AccessMethod activeAccessMethod = QNearFieldTarget::UnknownAccess; + bool scheduleSession(QNearFieldTarget::AccessMethod accessMethod); void startSession(); bool startNdefSession(); void stopSession(const QString &error); @@ -73,6 +75,7 @@ private Q_SLOTS: void onTagDiscovered(void *target); void onTargetLost(QNearFieldTargetPrivateImpl *target); void onDidInvalidateWithError(bool doRestart); + void onSessionTimer(); }; |