summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java129
-rw-r--r--src/plugins/position/android/src/jnipositioning.cpp167
-rw-r--r--src/plugins/position/android/src/jnipositioning.h7
-rw-r--r--src/plugins/position/android/src/plugin.json2
-rw-r--r--src/plugins/position/android/src/positionfactory_android.cpp5
-rw-r--r--src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp218
-rw-r--r--src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h88
-rw-r--r--src/plugins/position/android/src/src.pro6
8 files changed, 590 insertions, 32 deletions
diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
index ac510793..1c6a755c 100644
--- a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
+++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
@@ -43,13 +43,17 @@ package org.qtproject.qt5.android.positioning;
import android.app.Activity;
import android.content.Context;
+import android.location.GpsSatellite;
+import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import android.util.Log;
@@ -66,7 +70,7 @@ public class QtPositioning implements LocationListener
The positionInfo instance to which this
QtPositioning instance is attached to.
*/
- private int positionInfoSource = 0;
+ private int nativeClassReference = 0;
/*
The provider type requested by Qt:
@@ -85,6 +89,8 @@ public class QtPositioning implements LocationListener
private Location lastGps = null;
/* The last received network update */
private Location lastNetwork = null;
+ /* If true this class acts as satellite signal monitor rather than location monitor */
+ private boolean isSatelliteUpdate = false;
private PositioningLooper looperThread;
@@ -174,8 +180,9 @@ public class QtPositioning implements LocationListener
boolean exceptionOccurred = false;
QtPositioning positioningListener = new QtPositioning();
positioningListener.setActiveLooper(true);
- positioningListener.positionInfoSource = androidClassKey;
+ positioningListener.nativeClassReference = androidClassKey;
positioningListener.expectedProviders = locationProvider;
+ positioningListener.isSatelliteUpdate = false;
if (updateInterval == 0)
updateInterval = 1000; //don't update more often than once per second
@@ -249,9 +256,10 @@ public class QtPositioning implements LocationListener
boolean exceptionOccurred = false;
QtPositioning positioningListener = new QtPositioning();
positioningListener.setActiveLooper(true);
- positioningListener.positionInfoSource = androidClassKey;
+ positioningListener.nativeClassReference = androidClassKey;
positioningListener.isSingleUpdate = true;
positioningListener.expectedProviders = locationProvider;
+ positioningListener.isSatelliteUpdate = false;
if ((locationProvider & 1) > 0) {
Log.d(TAG, "Single update using GPS");
@@ -298,6 +306,57 @@ public class QtPositioning implements LocationListener
}
}
+ static public int startSatelliteUpdates(int androidClassKey, int updateInterval, boolean isSingleRequest)
+ {
+ synchronized (m_syncObject) {
+ try {
+ boolean exceptionOccurred = false;
+ QtPositioning positioningListener = new QtPositioning();
+ positioningListener.isSatelliteUpdate = true;
+ positioningListener.setActiveLooper(true);
+ positioningListener.nativeClassReference = androidClassKey;
+ positioningListener.expectedProviders = 1; //always satellite provider
+ positioningListener.isSingleUpdate = isSingleRequest;
+
+ if (updateInterval == 0)
+ updateInterval = 1000; //don't update more often than once per second
+
+ if (isSingleRequest)
+ Log.d(TAG, "Single update for Satellites " + updateInterval);
+ else
+ Log.d(TAG, "Regular updates for Satellites " + updateInterval);
+ try {
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
+ updateInterval, 0,
+ positioningListener,
+ positioningListener.looper());
+ } catch (SecurityException se) {
+ se.printStackTrace();
+ exceptionOccurred = true;
+ }
+
+ if (exceptionOccurred) {
+ positioningListener.setActiveLooper(false);
+ locationManager.removeUpdates(positioningListener);
+ return 0; //QGeoSatelliteInfoSource::AccessError
+ }
+
+ if (!expectedProvidersAvailable(positioningListener.expectedProviders)) {
+ //all location providers unavailable -> when they come back we resume automatically
+ //in the mean time return ClosedError
+ return 1; //QGeoSatelliteInfoSource::ClosedError
+ }
+
+ runningListeners.put(androidClassKey, positioningListener);
+ } catch(Exception e) {
+ e.printStackTrace();
+ return -1; //QGeoSatelliteInfoSource::UnknownSourceError
+ }
+
+ return 2; //QGeoSatelliteInfoSource::NoError
+ }
+ }
+
public QtPositioning()
{
looperThread = new PositioningLooper();
@@ -315,6 +374,8 @@ public class QtPositioning implements LocationListener
if (looperThread.isAlive())
return;
+ looperThread.isSatelliteListener(true);
+
looperThread.start();
while (!looperThread.isReady());
Thread.sleep(1000);
@@ -326,9 +387,11 @@ public class QtPositioning implements LocationListener
}
}
- private class PositioningLooper extends Thread {
+ private class PositioningLooper extends Thread implements GpsStatus.Listener{
private boolean looperRunning;
private Looper posLooper;
+ private boolean isSatelliteLooper = false;
+ private LocationManager locManager = null;
private PositioningLooper()
{
@@ -340,6 +403,15 @@ public class QtPositioning implements LocationListener
Looper.prepare();
Handler handler = new Handler();
looperRunning = true;
+
+ if (isSatelliteLooper) {
+ try {
+ locationManager.addGpsStatusListener(this);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
posLooper = Looper.myLooper();
Looper.loop();
looperRunning = false;
@@ -347,6 +419,8 @@ public class QtPositioning implements LocationListener
public void quitLooper()
{
+ if (isSatelliteLooper)
+ locationManager.removeGpsStatusListener(this);
looper().quit();
}
@@ -355,16 +429,48 @@ public class QtPositioning implements LocationListener
return looperRunning;
}
+ public void isSatelliteListener(boolean isListener)
+ {
+ isSatelliteLooper = isListener;
+ }
+
public Looper looper()
{
return posLooper;
}
+
+ @Override
+ public void onGpsStatusChanged(int event) {
+ switch (event) {
+ case GpsStatus.GPS_EVENT_FIRST_FIX:
+ break;
+ case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
+ GpsStatus status = locationManager.getGpsStatus(null);
+ Iterable<GpsSatellite> iterable = status.getSatellites();
+ Iterator<GpsSatellite> it = iterable.iterator();
+
+ ArrayList<GpsSatellite> list = new ArrayList<GpsSatellite>();
+ while (it.hasNext()) {
+ GpsSatellite sat = (GpsSatellite) it.next();
+ list.add(sat);
+ }
+ GpsSatellite[] sats = list.toArray(new GpsSatellite[list.size()]);
+ satelliteUpdated(sats, nativeClassReference, isSingleUpdate);
+
+ break;
+ case GpsStatus.GPS_EVENT_STARTED:
+ break;
+ case GpsStatus.GPS_EVENT_STOPPED:
+ break;
+ }
+ }
}
public static native void positionUpdated(Location update, int androidClassKey, boolean isSingleUpdate);
public static native void locationProvidersDisabled(int androidClassKey);
+ public static native void satelliteUpdated(GpsSatellite[] update, int androidClassKey, boolean isSingleUpdate);
@Override
public void onLocationChanged(Location location) {
@@ -372,8 +478,11 @@ public class QtPositioning implements LocationListener
if (location == null)
return;
+ if (isSatelliteUpdate) //we are a QGeoSatelliteInfoSource -> ignore
+ return;
+
if (isSingleUpdate || expectedProviders < 3) {
- positionUpdated(location, positionInfoSource, isSingleUpdate);
+ positionUpdated(location, nativeClassReference, isSingleUpdate);
return;
}
@@ -387,12 +496,12 @@ public class QtPositioning implements LocationListener
lastGps = location;
// assumption: GPS always better -> pass it on
- positionUpdated(location, positionInfoSource, isSingleUpdate);
+ positionUpdated(location, nativeClassReference, isSingleUpdate);
} else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
lastNetwork = location;
if (lastGps == null) { //no GPS fix yet use network location
- positionUpdated(location, positionInfoSource, isSingleUpdate);
+ positionUpdated(location, nativeClassReference, isSingleUpdate);
return;
}
@@ -404,7 +513,7 @@ public class QtPositioning implements LocationListener
return;
// Use network data -> GPS has timed out on updateInterval
- positionUpdated(location, positionInfoSource, isSingleUpdate);
+ positionUpdated(location, nativeClassReference, isSingleUpdate);
}
}
@@ -420,6 +529,6 @@ public class QtPositioning implements LocationListener
public void onProviderDisabled(String provider) {
Log.d(TAG, "Disabled provider: " + provider);
if (!expectedProvidersAvailable(expectedProviders))
- locationProvidersDisabled(positionInfoSource);
- }
+ locationProvidersDisabled(nativeClassReference);
+ }
}
diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp
index 035fb760..67b9fe4a 100644
--- a/src/plugins/position/android/src/jnipositioning.cpp
+++ b/src/plugins/position/android/src/jnipositioning.cpp
@@ -40,12 +40,14 @@
****************************************************************************/
#include <QDateTime>
+#include <QDebug>
#include <QMap>
#include <QtGlobal>
#include <android/log.h>
#include <jni.h>
#include <QGeoPositionInfo>
#include "qgeopositioninfosource_android_p.h"
+#include "qgeosatelliteinfosource_android_p.h"
#include "jnipositioning.h"
@@ -57,14 +59,19 @@ static jmethodID lastKnownPositionMethodId;
static jmethodID startUpdatesMethodId;
static jmethodID stopUpdatesMethodId;
static jmethodID requestUpdateMethodId;
+static jmethodID startSatelliteUpdatesMethodId;
static const char logTag[] = "QtPositioning";
static const char classErrorMsg[] = "Can't find class \"%s\"";
static const char methodErrorMsg[] = "Can't find method \"%s%s\"";
namespace AndroidPositioning {
-typedef QMap<int, QGeoPositionInfoSourceAndroid * > PositionSourceMap;
-Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
+ typedef QMap<int, QGeoPositionInfoSourceAndroid * > PositionSourceMap;
+ typedef QMap<int, QGeoSatelliteInfoSourceAndroid * > SatelliteSourceMap;
+
+ Q_GLOBAL_STATIC(PositionSourceMap, idToPosSource)
+
+ Q_GLOBAL_STATIC(SatelliteSourceMap, idToSatSource)
struct AttachedJNIEnv
{
@@ -90,7 +97,7 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
JNIEnv *jniEnv;
};
- int registerPositionInfoSource(QGeoPositionInfoSourceAndroid *src)
+ int registerPositionInfoSource(QObject *obj)
{
static bool firstInit = true;
if (firstInit) {
@@ -98,18 +105,32 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
firstInit = false;
}
- int key;
- do {
- key = qrand();
- } while (idToSource()->contains(key));
+ int key = -1;
+ if (obj->inherits("QGeoPositionInfoSource")) {
+ QGeoPositionInfoSourceAndroid *src = qobject_cast<QGeoPositionInfoSourceAndroid *>(obj);
+ Q_ASSERT(src);
+ do {
+ key = qrand();
+ } while (idToPosSource()->contains(key));
+
+ idToPosSource()->insert(key, src);
+ } else if (obj->inherits("QGeoSatelliteInfoSource")) {
+ QGeoSatelliteInfoSourceAndroid *src = qobject_cast<QGeoSatelliteInfoSourceAndroid *>(obj);
+ Q_ASSERT(src);
+ do {
+ key = qrand();
+ } while (idToSatSource()->contains(key));
+
+ idToSatSource()->insert(key, src);
+ }
- idToSource()->insert(key, src);
return key;
}
void unregisterPositionInfoSource(int key)
{
- idToSource()->remove(key);
+ idToPosSource()->remove(key);
+ idToSatSource()->remove(key);
}
enum PositionProvider
@@ -210,6 +231,70 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
return info;
}
+ QList<QGeoSatelliteInfo> satelliteInfoFromJavaLocation(JNIEnv *jniEnv,
+ jobjectArray satellites,
+ QList<QGeoSatelliteInfo>* usedInFix)
+ {
+ QList<QGeoSatelliteInfo> sats;
+ jsize length = jniEnv->GetArrayLength(satellites);
+ for (int i = 0; i<length; i++) {
+ jobject element = jniEnv->GetObjectArrayElement(satellites, i);
+ if (jniEnv->ExceptionOccurred()) {
+ qWarning() << "Cannot process all satellite data due to exception.";
+ break;
+ }
+
+ jclass thisClass = jniEnv->GetObjectClass(element);
+ if (!thisClass)
+ continue;
+
+ QGeoSatelliteInfo info;
+
+ //signal strength
+ jmethodID mid = jniEnv->GetMethodID(thisClass, "getSnr", "()F");
+ jfloat snr = jniEnv->CallFloatMethod(element, mid);
+ info.setSignalStrength((int)snr);
+
+ //ignore any satellite with no signal whatsoever
+ if (qFuzzyIsNull(snr))
+ continue;
+
+ //prn
+ mid = jniEnv->GetMethodID(thisClass, "getPrn", "()I");
+ jint prn = jniEnv->CallIntMethod(element, mid);
+ info.setSatelliteIdentifier(prn);
+
+ if (prn >= 1 && prn <= 32)
+ info.setSatelliteSystem(QGeoSatelliteInfo::GPS);
+ else if (prn >= 65 && prn <= 96)
+ info.setSatelliteSystem(QGeoSatelliteInfo::GLONASS);
+
+ //azimuth
+ mid = jniEnv->GetMethodID(thisClass, "getAzimuth", "()F");
+ jfloat azimuth = jniEnv->CallFloatMethod(element, mid);
+ info.setAttribute(QGeoSatelliteInfo::Azimuth, azimuth);
+
+ //elevation
+ mid = jniEnv->GetMethodID(thisClass, "getElevation", "()F");
+ jfloat elevation = jniEnv->CallFloatMethod(element, mid);
+ info.setAttribute(QGeoSatelliteInfo::Elevation, elevation);
+
+ //used in a fix
+ mid = jniEnv->GetMethodID(thisClass, "usedInFix", "()Z");
+ jboolean inFix = jniEnv->CallBooleanMethod(element, mid);
+
+ sats.append(info);
+
+ if (inFix)
+ usedInFix->append(info);
+
+ jniEnv->DeleteLocalRef(thisClass);
+ jniEnv->DeleteLocalRef(element);
+ }
+
+ return sats;
+ }
+
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly)
{
AttachedJNIEnv env;
@@ -242,7 +327,7 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
if (!env.jniEnv)
return QGeoPositionInfoSource::UnknownSourceError;
- QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToSource()->value(androidClassKey);
+ QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId,
@@ -279,7 +364,7 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
if (!env.jniEnv)
return QGeoPositionInfoSource::UnknownSourceError;
- QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToSource()->value(androidClassKey);
+ QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId,
@@ -297,6 +382,35 @@ Q_GLOBAL_STATIC(PositionSourceMap, idToSource)
}
return QGeoPositionInfoSource::UnknownSourceError;
}
+
+ QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int requestTimeout)
+ {
+ AttachedJNIEnv env;
+ if (!env.jniEnv)
+ return QGeoSatelliteInfoSource::UnknownSourceError;
+
+ QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey);
+
+ if (source) {
+ int interval = source->updateInterval();
+ if (isSingleRequest)
+ interval = requestTimeout;
+ int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startSatelliteUpdatesMethodId,
+ androidClassKey,
+ interval, isSingleRequest);
+ switch (errorCode) {
+ case -1:
+ case 0:
+ case 1:
+ case 2:
+ return static_cast<QGeoSatelliteInfoSource::Error>(errorCode);
+ default:
+ qWarning() << "startSatelliteUpdates: Unknown error code " << errorCode;
+ break;
+ }
+ }
+ return QGeoSatelliteInfoSource::UnknownSourceError;
+ }
}
@@ -304,7 +418,7 @@ static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jin
{
QGeoPositionInfo info = AndroidPositioning::positionInfoFromJavaLocation(env, location);
- QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToSource()->value(androidClassKey);
+ QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (!source) {
qFatal("positionUpdated: source == 0");
return;
@@ -317,14 +431,14 @@ static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jin
else
QMetaObject::invokeMethod(source, "processSinglePositionUpdate", Qt::AutoConnection,
Q_ARG(QGeoPositionInfo, info));
-
-
}
static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androidClassKey)
{
Q_UNUSED(env);
- QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToSource()->value(androidClassKey);
+ QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
+ if (!source)
+ source = AndroidPositioning::idToSatSource()->value(androidClassKey);
if (!source) {
qFatal("locationProvidersDisabled: source == 0");
return;
@@ -333,6 +447,24 @@ static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androi
QMetaObject::invokeMethod(source, "locationProviderDisabled", Qt::AutoConnection);
}
+static void satelliteUpdated(JNIEnv *env, jobject /*thiz*/, jobjectArray satellites, jint androidClassKey, jboolean isSingleUpdate)
+{
+ QList<QGeoSatelliteInfo> inUse;
+ QList<QGeoSatelliteInfo> sats = AndroidPositioning::satelliteInfoFromJavaLocation(env, satellites, &inUse);
+
+ QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey);
+ if (!source) {
+ qFatal("satelliteUpdated: source == 0");
+ return;
+ }
+
+ QMetaObject::invokeMethod(source, "processSatelliteUpdateInView", Qt::AutoConnection,
+ Q_ARG(QList<QGeoSatelliteInfo>, sats), Q_ARG(bool, isSingleUpdate));
+
+ QMetaObject::invokeMethod(source, "processSatelliteUpdateInUse", Qt::AutoConnection,
+ Q_ARG(QList<QGeoSatelliteInfo>, inUse), Q_ARG(bool, isSingleUpdate));
+}
+
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
clazz = env->FindClass(CLASS_NAME); \
@@ -350,7 +482,8 @@ if (!VAR) { \
static JNINativeMethod methods[] = {
{"positionUpdated", "(Landroid/location/Location;IZ)V", (void *)positionUpdated},
- {"locationProvidersDisabled", "(I)V", (void *) locationProvidersDisabled}
+ {"locationProvidersDisabled", "(I)V", (void *) locationProvidersDisabled},
+ {"satelliteUpdated", "([Landroid/location/GpsSatellite;IZ)V", (void *)satelliteUpdated}
};
static bool registerNatives(JNIEnv *env)
@@ -369,6 +502,8 @@ static bool registerNatives(JNIEnv *env)
GET_AND_CHECK_STATIC_METHOD(startUpdatesMethodId, positioningClass, "startUpdates", "(III)I");
GET_AND_CHECK_STATIC_METHOD(stopUpdatesMethodId, positioningClass, "stopUpdates", "(I)V");
GET_AND_CHECK_STATIC_METHOD(requestUpdateMethodId, positioningClass, "requestUpdate", "(II)I");
+ GET_AND_CHECK_STATIC_METHOD(startSatelliteUpdatesMethodId, positioningClass, "startSatelliteUpdates", "(IIZ)I");
+
return true;
}
diff --git a/src/plugins/position/android/src/jnipositioning.h b/src/plugins/position/android/src/jnipositioning.h
index de30107a..51341720 100644
--- a/src/plugins/position/android/src/jnipositioning.h
+++ b/src/plugins/position/android/src/jnipositioning.h
@@ -43,10 +43,11 @@
#define JNIPOSITIONING_H
#include <QGeoPositionInfoSource>
+#include <QGeoSatelliteInfoSource>
namespace AndroidPositioning
{
- int registerPositionInfoSource(QGeoPositionInfoSourceAndroid *src);
+ int registerPositionInfoSource(QObject *obj);
void unregisterPositionInfoSource(int key);
QGeoPositionInfoSource::PositioningMethods availableProviders();
@@ -55,6 +56,10 @@ namespace AndroidPositioning
QGeoPositionInfoSource::Error startUpdates(int androidClassKey);
void stopUpdates(int androidClassKey);
QGeoPositionInfoSource::Error requestUpdate(int androidClassKey);
+
+ QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey,
+ bool isSingleRequest,
+ int updateRequestTimeout);
}
#endif // JNIPOSITIONING_H
diff --git a/src/plugins/position/android/src/plugin.json b/src/plugins/position/android/src/plugin.json
index 35823b5e..b84fafea 100644
--- a/src/plugins/position/android/src/plugin.json
+++ b/src/plugins/position/android/src/plugin.json
@@ -2,7 +2,7 @@
"Keys": ["android"],
"Provider": "android",
"Position": true,
- "Satellite": false,
+ "Satellite": true,
"Monitor": false,
"Priority": 1000
}
diff --git a/src/plugins/position/android/src/positionfactory_android.cpp b/src/plugins/position/android/src/positionfactory_android.cpp
index 57f2d57f..047c313d 100644
--- a/src/plugins/position/android/src/positionfactory_android.cpp
+++ b/src/plugins/position/android/src/positionfactory_android.cpp
@@ -41,6 +41,7 @@
#include "positionfactory_android.h"
#include "qgeopositioninfosource_android_p.h"
+#include "qgeosatelliteinfosource_android_p.h"
QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryAndroid::positionInfoSource(QObject *parent)
{
@@ -50,8 +51,8 @@ QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryAndroid::positionInfoSource
QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryAndroid::satelliteInfoSource(QObject *parent)
{
- Q_UNUSED(parent);
- return 0;
+ QGeoSatelliteInfoSourceAndroid *src = new QGeoSatelliteInfoSourceAndroid(parent);
+ return src;
}
QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryAndroid::areaMonitor(QObject *parent)
diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp
new file mode 100644
index 00000000..f9e627d0
--- /dev/null
+++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+
+#include "qgeosatelliteinfosource_android_p.h"
+#include "jnipositioning.h"
+
+Q_DECLARE_METATYPE(QGeoSatelliteInfo)
+Q_DECLARE_METATYPE(QList<QGeoSatelliteInfo>)
+
+#define UPDATE_FROM_COLD_START 2*60*1000
+
+QGeoSatelliteInfoSourceAndroid::QGeoSatelliteInfoSourceAndroid(QObject *parent) :
+ QGeoSatelliteInfoSource(parent), m_error(NoError), updatesRunning(false)
+{
+ qRegisterMetaType< QGeoSatelliteInfo >();
+ qRegisterMetaType< QList<QGeoSatelliteInfo> >();
+ androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this);
+ androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this);
+
+ requestTimer.setSingleShot(true);
+ QObject::connect(&requestTimer, SIGNAL(timeout()),
+ this, SLOT(requestTimeout()));
+}
+
+QGeoSatelliteInfoSourceAndroid::~QGeoSatelliteInfoSourceAndroid()
+{
+ stopUpdates();
+
+ if (requestTimer.isActive()) {
+ requestTimer.stop();
+ AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest);
+ }
+
+ AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForUpdate);
+ AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest);
+}
+
+
+void QGeoSatelliteInfoSourceAndroid::setUpdateInterval(int msec)
+{
+ int previousInterval = updateInterval();
+ msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec;
+
+ if (msec == previousInterval)
+ return;
+
+ QGeoSatelliteInfoSource::setUpdateInterval(msec);
+
+ if (updatesRunning)
+ reconfigureRunningSystem();
+}
+
+int QGeoSatelliteInfoSourceAndroid::minimumUpdateInterval() const
+{
+ return 1000;
+}
+
+QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceAndroid::error() const
+{
+ return m_error;
+}
+
+void QGeoSatelliteInfoSourceAndroid::startUpdates()
+{
+ if (updatesRunning)
+ return;
+
+ updatesRunning = true;
+
+ QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates(
+ androidClassKeyForUpdate, false, updateInterval());
+ if (error != QGeoSatelliteInfoSource::NoError) {
+ updatesRunning = false;
+ m_error = error;
+ emit QGeoSatelliteInfoSource::error(m_error);
+ }
+}
+
+void QGeoSatelliteInfoSourceAndroid::stopUpdates()
+{
+ if (!updatesRunning)
+ return;
+
+ updatesRunning = false;
+ AndroidPositioning::stopUpdates(androidClassKeyForUpdate);
+}
+
+void QGeoSatelliteInfoSourceAndroid::requestUpdate(int timeout)
+{
+ if (requestTimer.isActive())
+ return;
+
+ if (timeout != 0 && timeout < minimumUpdateInterval()) {
+ emit requestTimeout();
+ return;
+ }
+
+ if (timeout == 0)
+ timeout = UPDATE_FROM_COLD_START;
+
+ requestTimer.start(timeout);
+
+ // if updates already running with interval equal or less then timeout
+ // then we wait for next update coming through
+ // assume that a single update will not be quicker than regular updates anyway
+ if (updatesRunning && updateInterval() <= timeout)
+ return;
+
+ QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates(
+ androidClassKeyForSingleRequest, true, timeout);
+ if (error != QGeoSatelliteInfoSource::NoError) {
+ requestTimer.stop();
+ m_error = error;
+ emit QGeoSatelliteInfoSource::error(m_error);
+ }
+}
+
+void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInView(const QList<QGeoSatelliteInfo> &satsInView, bool isSingleUpdate)
+{
+ if (!isSingleUpdate) {
+ //if requested while regular updates were running
+ if (requestTimer.isActive())
+ requestTimer.stop();
+ emit QGeoSatelliteInfoSource::satellitesInViewUpdated(satsInView);
+ return;
+ }
+
+ m_satsInView = satsInView;
+}
+
+void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInUse(const QList<QGeoSatelliteInfo> &satsInUse, bool isSingleUpdate)
+{
+ if (!isSingleUpdate) {
+ //if requested while regular updates were running
+ if (requestTimer.isActive())
+ requestTimer.stop();
+ emit QGeoSatelliteInfoSource::satellitesInUseUpdated(satsInUse);
+ return;
+ }
+
+ m_satsInUse = satsInUse;
+}
+
+void QGeoSatelliteInfoSourceAndroid::requestTimeout()
+{
+ AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest);
+
+ const int count = m_satsInView.count();
+ if (!count) {
+ emit requestTimeout();
+ return;
+ }
+
+ emit QGeoSatelliteInfoSource::satellitesInViewUpdated(m_satsInView);
+ emit QGeoSatelliteInfoSource::satellitesInUseUpdated(m_satsInUse);
+
+ m_satsInUse.clear();
+ m_satsInView.clear();
+}
+
+/*
+ Updates the system assuming that updateInterval
+ and/or preferredPositioningMethod have changed.
+ */
+void QGeoSatelliteInfoSourceAndroid::reconfigureRunningSystem()
+{
+ if (!updatesRunning)
+ return;
+
+ stopUpdates();
+ startUpdates();
+}
+
+void QGeoSatelliteInfoSourceAndroid::locationProviderDisabled()
+{
+ m_error = QGeoSatelliteInfoSource::ClosedError;
+ emit QGeoSatelliteInfoSource::error(m_error);
+}
diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h
new file mode 100644
index 00000000..75711a3e
--- /dev/null
+++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QGEOSATELLITEINFOSOURCEANDROID_H
+#define QGEOSATELLITEINFOSOURCEANDROID_H
+
+#include <QGeoSatelliteInfoSource>
+#include <QTimer>
+
+class QGeoSatelliteInfoSourceAndroid : public QGeoSatelliteInfoSource
+{
+ Q_OBJECT
+public:
+ explicit QGeoSatelliteInfoSourceAndroid(QObject *parent = 0);
+ ~QGeoSatelliteInfoSourceAndroid();
+
+ //From QGeoSatelliteInfoSource
+ void setUpdateInterval(int msec);
+ int minimumUpdateInterval() const;
+
+ Error error() const;
+
+public Q_SLOTS:
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int timeout = 0);
+
+ void processSatelliteUpdateInView(const QList<QGeoSatelliteInfo> &satsInView, bool isSingleUpdate);
+ void processSatelliteUpdateInUse(const QList<QGeoSatelliteInfo> &satsInUse, bool isSingleUpdate);
+
+ void locationProviderDisabled();
+private Q_SLOTS:
+ void requestTimeout();
+
+private:
+ void reconfigureRunningSystem();
+
+ Error m_error;
+ int androidClassKeyForUpdate;
+ int androidClassKeyForSingleRequest;
+ bool updatesRunning;
+
+ QTimer requestTimer;
+ QList<QGeoSatelliteInfo> m_satsInUse;
+ QList<QGeoSatelliteInfo> m_satsInView;
+
+};
+
+#endif // QGEOSATELLITEINFOSOURCEANDROID_H
diff --git a/src/plugins/position/android/src/src.pro b/src/plugins/position/android/src/src.pro
index 52e57bd3..a61b77b5 100644
--- a/src/plugins/position/android/src/src.pro
+++ b/src/plugins/position/android/src/src.pro
@@ -8,11 +8,13 @@ load(qt_plugin)
HEADERS = \
positionfactory_android.h \
qgeopositioninfosource_android_p.h \
- jnipositioning.h
+ jnipositioning.h \
+ qgeosatelliteinfosource_android_p.h
SOURCES = \
positionfactory_android.cpp \
qgeopositioninfosource_android.cpp \
- jnipositioning.cpp
+ jnipositioning.cpp \
+ qgeosatelliteinfosource_android.cpp
OTHER_FILES = plugin.json