Commit b17c07dc authored by Oliver Wolff's avatar Oliver Wolff
Browse files

winrt: Initialize position source on first usage


Loading the plugin without access to the location service will
work and not error out. It is still possible to enable location service
later and the backend will work as expected.

This patch changes the behavior so that the pop up asking for access to
the user's location data is no longer shown when the plugin is loaded, but
when the backend is actually used for the first time.

Change-Id: I23100f7867610c6f23b2d2ea5c15c268468949a9
Reviewed-by: default avatarMiguel Costa <miguel.costa@qt.io>
parent 379f398c
No related merge requests found
Showing with 54 additions and 24 deletions
......@@ -106,6 +106,12 @@ static inline HRESULT await(const ComPtr<IAsyncOperation<GeolocationAccessStatus
}
#endif // !Q_OS_WINRT
enum class InitializationState {
Uninitialized,
Initializing,
Initialized
};
class QGeoPositionInfoSourceWinRTPrivate {
public:
ComPtr<IGeolocator> locator;
......@@ -118,6 +124,8 @@ public:
QMutex mutex;
bool updatesOngoing = false;
int minimumUpdateInterval = -1;
int updateInterval = -1;
InitializationState initState = InitializationState::Uninitialized;
PositionStatus positionStatus = PositionStatus_NotInitialized;
};
......@@ -144,9 +152,16 @@ QGeoPositionInfoSourceWinRT::~QGeoPositionInfoSourceWinRT()
int QGeoPositionInfoSourceWinRT::init()
{
qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
Q_ASSERT(d->initState != InitializationState::Initializing);
if (d->initState == InitializationState::Initialized)
return 0;
qCDebug(lcPositioningWinRT) << __FUNCTION__;
d->initState = InitializationState::Initializing;
if (!requestAccess()) {
d->initState = InitializationState::Uninitialized;
setError(QGeoPositionInfoSource::AccessError);
qWarning ("Location access failed.");
return -1;
}
......@@ -155,35 +170,37 @@ int QGeoPositionInfoSourceWinRT::init()
&d->locator);
RETURN_HR_IF_FAILED("Could not initialize native location services.");
UINT32 interval;
hr = d->locator->get_ReportInterval(&interval);
RETURN_HR_IF_FAILED("Could not retrieve report interval.");
d->minimumUpdateInterval = static_cast<int>(interval);
setUpdateInterval(d->minimumUpdateInterval);
if (d->minimumUpdateInterval == -1) {
UINT32 interval;
hr = d->locator->get_ReportInterval(&interval);
RETURN_HR_IF_FAILED("Could not retrieve report interval.");
d->minimumUpdateInterval = static_cast<int>(interval);
}
if (d->updateInterval == -1)
d->updateInterval = d->minimumUpdateInterval;
setUpdateInterval(d->updateInterval);
return hr;
});
if (FAILED(hr)) {
d->initState = InitializationState::Uninitialized;
setError(QGeoPositionInfoSource::UnknownSourceError);
return -1;
}
hr = d->locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default);
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
qErrnoWarning(hr, "Could not initialize desired accuracy.");
return -1;
}
d->periodicTimer.setSingleShot(true);
connect(&d->periodicTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::virtualPositionUpdate);
d->singleUpdateTimer.setSingleShot(true);
connect(&d->singleUpdateTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::singleUpdateTimeOut);
setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods);
QGeoPositionInfoSource::PositioningMethods preferredMethods = preferredPositioningMethods();
if (preferredMethods == QGeoPositionInfoSource::NoPositioningMethods)
preferredMethods = QGeoPositionInfoSource::AllPositioningMethods;
setPreferredPositioningMethods(preferredMethods);
connect(this, &QGeoPositionInfoSourceWinRT::nativePositionUpdate, this, &QGeoPositionInfoSourceWinRT::updateSynchronized);
d->initState = InitializationState::Initialized;
return 0;
}
......@@ -208,9 +225,12 @@ void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInf
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
if (previousPreferredPositioningMethods == preferredPositioningMethods())
if (previousPreferredPositioningMethods == preferredPositioningMethods()
|| d->initState != InitializationState::Uninitialized) {
return;
}
Q_ASSERT(d->initState != InitializationState::Initializing);
const bool needsRestart = d->positionToken.value != 0 || d->statusToken.value != 0;
if (needsRestart)
......@@ -232,6 +252,12 @@ void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
{
qCDebug(lcPositioningWinRT) << __FUNCTION__ << msec;
Q_D(QGeoPositionInfoSourceWinRT);
if (d->initState == InitializationState::Uninitialized) {
d->updateInterval = msec;
return;
}
Q_ASSERT(d->initState != InitializationState::Initializing);
// minimumUpdateInterval is initialized to the lowest possible update interval in init().
// Passing 0 will cause an error on Windows 10.
// See https://docs.microsoft.com/en-us/uwp/api/windows.devices.geolocation.geolocator.reportinterval
......@@ -250,9 +276,10 @@ void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
return;
}
d->periodicTimer.setInterval(qMax(msec, minimumUpdateInterval()));
d->updateInterval = msec;
d->periodicTimer.setInterval(d->updateInterval);
QGeoPositionInfoSource::setUpdateInterval(msec);
QGeoPositionInfoSource::setUpdateInterval(d->updateInterval);
if (needsRestart)
startHandler();
......@@ -261,7 +288,7 @@ void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
int QGeoPositionInfoSourceWinRT::minimumUpdateInterval() const
{
Q_D(const QGeoPositionInfoSourceWinRT);
return d->minimumUpdateInterval;
return d->minimumUpdateInterval == -1 ? 1000 : d->minimumUpdateInterval;
}
void QGeoPositionInfoSourceWinRT::startUpdates()
......@@ -270,6 +297,9 @@ void QGeoPositionInfoSourceWinRT::startUpdates()
Q_D(QGeoPositionInfoSourceWinRT);
setError(QGeoPositionInfoSource::NoError);
if (init() < 0)
return;
if (d->updatesOngoing)
return;
......@@ -284,6 +314,9 @@ void QGeoPositionInfoSourceWinRT::stopUpdates()
qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
if (init() < 0)
return;
stopHandler();
d->updatesOngoing = false;
d->periodicTimer.stop();
......@@ -358,6 +391,9 @@ void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout)
qCDebug(lcPositioningWinRT) << __FUNCTION__ << timeout;
Q_D(QGeoPositionInfoSourceWinRT);
if (init() < 0)
return;
setError(QGeoPositionInfoSource::NoError);
if (timeout != 0 && timeout < minimumUpdateInterval()) {
emit updateTimeout();
......
......@@ -47,12 +47,6 @@ QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinRT::positionInfoSource(Q
{
qCDebug(lcPositioningWinRT) << __FUNCTION__;
QGeoPositionInfoSourceWinRT *src = new QGeoPositionInfoSourceWinRT(parent);
if (src->init() < 0) {
qCDebug(lcPositioningWinRT) << __FUNCTION__ << "Source initialization failed.";
delete src;
return nullptr;
}
qCDebug(lcPositioningWinRT) << __FUNCTION__ << "Created position info source.";
return src;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment