7#include <QGeoPositionInfo>
10using namespace Qt::StringLiterals;
19 QGeoPositionInfoSource(parent)
21 androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(
this);
22 androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(
this);
24 parseParameters(parameters);
27 setPreferredPositioningMethods(AllPositioningMethods);
29 m_requestTimer.setSingleShot(
true);
30 connect(&m_requestTimer, &QTimer::timeout,
this,
31 &QGeoPositionInfoSourceAndroid::requestTimeout);
33 m_regularUpdatesTimer.setSingleShot(
false);
34 connect(&m_regularUpdatesTimer, &QTimer::timeout,
this,
42 if (m_requestTimer.isActive()) {
43 m_requestTimer.stop();
53 int previousInterval = updateInterval();
56 if (msec == previousInterval)
59 QGeoPositionInfoSource::setUpdateInterval(msec);
62 reconfigureRunningSystem();
67 return AndroidPositioning::lastKnownPosition(fromSatellitePositioningMethodsOnly,
73 return AndroidPositioning::availableProviders();
78 PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
79 QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
80 if (previousPreferredPositioningMethods == preferredPositioningMethods())
84 reconfigureRunningSystem();
99 return m_useAltitudeConverter;
105 if (error != QGeoPositionInfoSource::NoError)
106 emit QGeoPositionInfoSource::errorOccurred(m_error);
111 m_useAltitudeConverter = parameters.value(kUseAltitudeConverter,
false).toBool();
119 m_error = QGeoPositionInfoSource::NoError;
121 if (preferredPositioningMethods() == 0) {
122 setError(UnknownSourceError);
126 updatesRunning =
true;
128 m_lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
129 m_regularUpdatesErrorRaised =
false;
130 QGeoPositionInfoSource::Error error = AndroidPositioning::startUpdates(androidClassKeyForUpdate);
131 if (error != QGeoPositionInfoSource::NoError) {
132 updatesRunning =
false;
135 m_regularUpdatesTimer.start(kRegularUpdatesTimerInterval);
144 updatesRunning =
false;
145 m_regularUpdatesTimer.stop();
151 if (m_requestTimer.isActive())
154 m_error = QGeoPositionInfoSource::NoError;
157 setError(QGeoPositionInfoSource::UpdateTimeoutError);
164 m_requestTimer.start(timeout);
169 if (updatesRunning && updateInterval() <= timeout)
172 const QGeoPositionInfoSource::Error error =
173 AndroidPositioning::requestUpdate(androidClassKeyForSingleRequest, timeout);
174 if (error != QGeoPositionInfoSource::NoError) {
175 m_requestTimer.stop();
183 if (m_requestTimer.isActive())
184 m_requestTimer.stop();
186 m_lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
187 m_regularUpdatesErrorRaised =
false;
189 emit positionUpdated(pInfo);
196 if (!m_requestTimer.isActive())
199 queuedSingleUpdates.append(pInfo);
203 const qsizetype maxPossibleUpdates =
204 (preferredPositioningMethods() == QGeoPositionInfoSource::AllPositioningMethods)
207 if (queuedSingleUpdates.size() == maxPossibleUpdates) {
208 m_requestTimer.stop();
215 if (updatesRunning && !m_regularUpdatesErrorRaised) {
216 m_regularUpdatesErrorRaised =
true;
217 setError(QGeoPositionInfoSource::UpdateTimeoutError);
220 setError(QGeoPositionInfoSource::ClosedError);
225 emit supportedPositioningMethodsChanged();
233 if (queuedSingleUpdates.isEmpty()) {
234 setError(QGeoPositionInfoSource::UpdateTimeoutError);
238 auto byAccuracy = [](
const QGeoPositionInfo &info,
const QGeoPositionInfo &best) {
240 const qint64 timeDelta = best.timestamp().secsTo(info.timestamp());
241 if (abs(timeDelta) > 20)
242 return timeDelta > 0;
245 if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) &&
246 best.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
248 return info.attribute(QGeoPositionInfo::HorizontalAccuracy) <
249 best.attribute(QGeoPositionInfo::HorizontalAccuracy);
253 if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
259 QGeoPositionInfo best = *std::min_element(queuedSingleUpdates.begin(),
260 queuedSingleUpdates.end(), byAccuracy);
261 queuedSingleUpdates.clear();
262 emit positionUpdated(best);
267 if (!m_regularUpdatesErrorRaised) {
268 const auto now = QDateTime::currentMSecsSinceEpoch();
269 if ((now - m_lastUpdateTime) > (updateInterval() + kUpdateFromColdStart)) {
270 m_regularUpdatesErrorRaised =
true;
271 setError(QGeoPositionInfoSource::UpdateTimeoutError);
277
278
279
bool useAltitudeConverter() const
virtual void stopUpdates() override
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly=false) const override
Returns an update containing the last known position, or a null update if none is available.
void processSinglePositionUpdate(const QGeoPositionInfo &pInfo)
void locationProvidersChanged()
~QGeoPositionInfoSourceAndroid()
virtual void requestUpdate(int timeout=0) override
void processPositionUpdate(const QGeoPositionInfo &pInfo)
void setPreferredPositioningMethods(PositioningMethods methods) override
void setUpdateInterval(int msec) override
int minimumUpdateInterval() const override
Error error() const override
Returns the type of error that last occurred.
PositioningMethods supportedPositioningMethods() const override
Returns the positioning methods available to this source.
void locationProviderDisabled()
void stopUpdates(int androidClassKey)
static constexpr auto kUseAltitudeConverter
static constexpr int kRegularUpdatesTimerInterval
static constexpr int kUpdateFromColdStart