Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qgeopositioninfosource_android.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "jnipositioning.h"
6#include <QGeoPositionInfo>
7
8static constexpr int kUpdateFromColdStart = 2 * 60 * 1000;
9static constexpr int kRegularUpdatesTimerInterval = 30 * 1000;
10
13{
14 androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this);
15 androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this);
16
17 //by default use all methods
19
20 m_requestTimer.setSingleShot(true);
21 connect(&m_requestTimer, &QTimer::timeout, this,
22 &QGeoPositionInfoSourceAndroid::requestTimeout);
23
24 m_regularUpdatesTimer.setSingleShot(false);
25 connect(&m_regularUpdatesTimer, &QTimer::timeout, this,
26 &QGeoPositionInfoSourceAndroid::regularUpdatesTimeout);
27}
28
30{
32
33 if (m_requestTimer.isActive()) {
34 m_requestTimer.stop();
35 AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest);
36 }
37
39 AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest);
40}
41
43{
44 int previousInterval = updateInterval();
45 msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec;
46
47 if (msec == previousInterval)
48 return;
49
51
52 if (updatesRunning)
53 reconfigureRunningSystem();
54}
55
56QGeoPositionInfo QGeoPositionInfoSourceAndroid::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
57{
58 return AndroidPositioning::lastKnownPosition(fromSatellitePositioningMethodsOnly);
59}
60
61QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceAndroid::supportedPositioningMethods() const
62{
64}
65
66void QGeoPositionInfoSourceAndroid::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods)
67{
68 PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
70 if (previousPreferredPositioningMethods == preferredPositioningMethods())
71 return;
72
73 if (updatesRunning)
74 reconfigureRunningSystem();
75}
76
78{
79 return 50;
80}
81
83{
84 return m_error;
85}
86
87void QGeoPositionInfoSourceAndroid::setError(Error error)
88{
89 m_error = error;
92}
93
95{
96 if (updatesRunning)
97 return;
98
100
101 if (preferredPositioningMethods() == 0) {
102 setError(UnknownSourceError);
103 return;
104 }
105
106 updatesRunning = true;
107 // Start calculating updates from now.
108 m_lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
109 m_regularUpdatesErrorRaised = false;
112 updatesRunning = false;
113 setError(error);
114 } else {
115 m_regularUpdatesTimer.start(kRegularUpdatesTimerInterval);
116 }
117}
118
120{
121 if (!updatesRunning)
122 return;
123
124 updatesRunning = false;
125 m_regularUpdatesTimer.stop();
126 AndroidPositioning::stopUpdates(androidClassKeyForUpdate);
127}
128
130{
131 if (m_requestTimer.isActive())
132 return;
133
135
136 if (timeout != 0 && timeout < minimumUpdateInterval()) {
138 return;
139 }
140
141 if (timeout == 0)
143
144 m_requestTimer.start(timeout);
145
146 // if updates already running with interval equal to timeout
147 // then we wait for next update coming through
148 // assume that a single update will not be quicker than regular updates anyway
149 if (updatesRunning && updateInterval() <= timeout)
150 return;
151
153 AndroidPositioning::requestUpdate(androidClassKeyForSingleRequest, timeout);
155 m_requestTimer.stop();
156 setError(error);
157 }
158}
159
161{
162 //single update request and served as part of regular update
163 if (m_requestTimer.isActive())
164 m_requestTimer.stop();
165
166 m_lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
167 m_regularUpdatesErrorRaised = false;
168
169 emit positionUpdated(pInfo);
170}
171
172// Might still be called multiple times (once for each provider)
174{
175 //timeout but we received a late update -> ignore
176 if (!m_requestTimer.isActive())
177 return;
178
179 queuedSingleUpdates.append(pInfo);
180 // Calculate the maximum amount of possibly received updates. It depends on
181 // preferred positioning methods. Two updates if we have both Satellite and
182 // Network, and only one otherwise.
183 const qsizetype maxPossibleUpdates =
185 ? 2 : 1;
186 // If we get the maximum number of updates, we do not need to wait for more
187 if (queuedSingleUpdates.size() == maxPossibleUpdates) {
188 m_requestTimer.stop();
189 requestTimeout();
190 }
191}
192
194{
195 if (updatesRunning && !m_regularUpdatesErrorRaised) {
196 m_regularUpdatesErrorRaised = true;
198 }
199
201}
202
204{
206}
207
208void QGeoPositionInfoSourceAndroid::requestTimeout()
209{
210 AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest);
211 //no queued update to process -> timeout
212
213 if (queuedSingleUpdates.isEmpty()) {
215 return;
216 }
217
218 auto byAccuracy = [](const QGeoPositionInfo &info, const QGeoPositionInfo &best) {
219 //anything newer by 20s is always better
220 const qint64 timeDelta = best.timestamp().secsTo(info.timestamp());
221 if (abs(timeDelta) > 20)
222 return timeDelta > 0;
223
224 //compare accuracy
225 if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) &&
226 best.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
227 {
230 }
231
232 //prefer info with accuracy information
234 return true;
235
236 return false;
237 };
238
239 QGeoPositionInfo best = *std::min_element(queuedSingleUpdates.begin(),
240 queuedSingleUpdates.end(), byAccuracy);
241 queuedSingleUpdates.clear();
242 emit positionUpdated(best);
243}
244
245void QGeoPositionInfoSourceAndroid::regularUpdatesTimeout()
246{
247 if (!m_regularUpdatesErrorRaised) {
249 if ((now - m_lastUpdateTime) > (updateInterval() + kUpdateFromColdStart)) {
250 m_regularUpdatesErrorRaised = true;
252 }
253 }
254}
255
256/*
257 Updates the system assuming that updateInterval
258 and/or preferredPositioningMethod have changed.
259 */
260void QGeoPositionInfoSourceAndroid::reconfigureRunningSystem()
261{
262 if (!updatesRunning)
263 return;
264
265 stopUpdates();
266 startUpdates();
267}
static JNINativeMethod methods[]
static qint64 currentMSecsSinceEpoch() noexcept
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)
virtual void requestUpdate(int timeout=0) override
void processPositionUpdate(const QGeoPositionInfo &pInfo)
void setPreferredPositioningMethods(PositioningMethods methods) 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.
\inmodule QtPositioning
int updateInterval
This property holds the requested interval in milliseconds between each update.
void positionUpdated(const QGeoPositionInfo &update)
If startUpdates() or requestUpdate() is called, this signal is emitted when an update becomes availab...
void errorOccurred(QGeoPositionInfoSource::Error)
This signal is emitted after an error occurred.
virtual void setPreferredPositioningMethods(PositioningMethods methods)
void supportedPositioningMethodsChanged()
This signal is emitted when the supported positioning methods changed.
Error
The Error enumeration represents the errors which can occur.
virtual void setUpdateInterval(int msec)
PositioningMethods preferredPositioningMethods
Sets the preferred positioning methods for this source.
\inmodule QtPositioning
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
iterator end()
Definition qlist.h:609
iterator begin()
Definition qlist.h:608
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void setSingleShot(bool singleShot)
Definition qtimer.cpp:580
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:208
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition qtimer.cpp:156
void stop()
Stops the timer.
Definition qtimer.cpp:226
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
void unregisterPositionInfoSource(int key)
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly)
int registerPositionInfoSource(QObject *obj)
QGeoPositionInfoSource::Error requestUpdate(int androidClassKey, int timeout)
QGeoPositionInfoSource::Error startUpdates(int androidClassKey)
QGeoPositionInfoSource::PositioningMethods availableProviders()
void stopUpdates(int androidClassKey)
DBusConnection const char DBusError * error
static constexpr int kUpdateFromColdStart
static constexpr int kRegularUpdatesTimerInterval
GLbitfield GLuint64 timeout
[4]
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
QFileInfo info(fileName)
[8]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent