Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
jnipositioning.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
4#include "jnipositioning.h"
7#include <QtPositioning/QGeoPositionInfo>
8#include <QtCore/QDateTime>
9#include <QtCore/QMap>
10#include <QtCore/QRandomGenerator>
11#include <QtCore/QJniEnvironment>
12#include <QtCore/QJniObject>
13#include <QtCore/QLoggingCategory>
14#include <QtCore/QPermission>
15#include <QtCore/QCoreApplication>
16#include <QtCore/QTimeZone>
17#include <android/log.h>
18
19Q_DECLARE_JNI_CLASS(QtPositioning, "org/qtproject/qt/android/positioning/QtPositioning")
20Q_DECLARE_JNI_CLASS(GnssStatus, "android/location/GnssStatus")
21Q_DECLARE_JNI_CLASS(Location, "android/location/Location")
22
23using namespace Qt::StringLiterals;
24
25template<typename T>
27{
28public:
31 {
32 if (m_classRef) {
34 if (env.jniEnv())
35 env->DeleteGlobalRef(m_classRef);
36 }
37 }
38
39 bool init()
40 {
42 if (env.jniEnv()) {
43 if (m_classRef) {
44 env->DeleteGlobalRef(m_classRef);
45 m_classRef = nullptr;
46 }
47
48 m_classRef = env.findClass<T>(); // it returns global ref!
49 }
50 return m_classRef != nullptr;
51 }
52
53 jclass operator()() { return m_classRef; }
54
55private:
56 jclass m_classRef = nullptr;
57};
58
60
61static jmethodID providerListMethodId;
63static jmethodID startUpdatesMethodId;
64static jmethodID stopUpdatesMethodId;
65static jmethodID requestUpdateMethodId;
67
68static const char logTag[] = "qt.positioning.android";
69static const char methodErrorMsg[] = "Can't find method \"%s%s\"";
70
71Q_LOGGING_CATEGORY(lcPositioning, logTag)
72
73namespace {
74
81class ConstellationMapper
82{
83public:
84 static bool init()
85 {
86 m_gnssStatusObject = nullptr;
87 if (QNativeInterface::QAndroidApplication::sdkVersion() > 23) {
88 m_gnssStatusObject = QJniEnvironment().findClass<QtJniTypes::GnssStatus>();
89 if (!m_gnssStatusObject)
90 return false;
91 }
92 // no need to query it for API level <= 23
93 return true;
94 }
95
96 static QGeoSatelliteInfo::SatelliteSystem toSatelliteSystem(int constellationType)
97 {
98 if (!m_gnssStatusObject)
100
101 static const int gps =
102 QJniObject::getStaticField<jint>(m_gnssStatusObject, "CONSTELLATION_GPS");
103 static const int glonass =
104 QJniObject::getStaticField<jint>(m_gnssStatusObject, "CONSTELLATION_GLONASS");
105 static const int galileo =
106 QJniObject::getStaticField<jint>(m_gnssStatusObject, "CONSTELLATION_GALILEO");
107 static const int beidou =
108 QJniObject::getStaticField<jint>(m_gnssStatusObject, "CONSTELLATION_BEIDOU");
109 static const int qzss =
110 QJniObject::getStaticField<jint>(m_gnssStatusObject, "CONSTELLATION_QZSS");
111
112 if (constellationType == gps) {
114 } else if (constellationType == glonass) {
116 } else if (constellationType == galileo) {
118 } else if (constellationType == beidou) {
120 } else if (constellationType == qzss){
122 } else {
123 qCWarning(lcPositioning) << "Unknown satellite system" << constellationType;
125 }
126 }
127
128private:
129 static jclass m_gnssStatusObject;
130};
131
132jclass ConstellationMapper::m_gnssStatusObject = nullptr;
133
134} // anonymous namespace
135
139
140 Q_GLOBAL_STATIC(PositionSourceMap, idToPosSource)
141
142 Q_GLOBAL_STATIC(SatelliteSourceMap, idToSatSource)
143
145 {
146 int key = -1;
147 if (obj->inherits("QGeoPositionInfoSource")) {
148 QGeoPositionInfoSourceAndroid *src = qobject_cast<QGeoPositionInfoSourceAndroid *>(obj);
149 Q_ASSERT(src);
150 do {
151 key = qAbs(int(QRandomGenerator::global()->generate()));
152 } while (idToPosSource()->contains(key));
153
154 idToPosSource()->insert(key, src);
155 } else if (obj->inherits("QGeoSatelliteInfoSource")) {
156 QGeoSatelliteInfoSourceAndroid *src = qobject_cast<QGeoSatelliteInfoSourceAndroid *>(obj);
157 Q_ASSERT(src);
158 do {
159 key = qAbs(int(QRandomGenerator::global()->generate()));
160 } while (idToSatSource()->contains(key));
161
162 idToSatSource()->insert(key, src);
163 }
164
165 return key;
166 }
167
169 {
170 if (idToPosSource.exists())
171 idToPosSource->remove(key);
172
173 if (idToSatSource.exists())
174 idToSatSource->remove(key);
175 }
176
178 {
182 };
183
184
185 QGeoPositionInfoSource::PositioningMethods availableProviders()
186 {
187 QGeoPositionInfoSource::PositioningMethods ret = QGeoPositionInfoSource::NoPositioningMethods;
188 QJniEnvironment env;
189 if (!env.jniEnv())
190 return ret;
191 QJniObject jniProvidersObj =
192 QJniObject::callStaticMethod<jobject>(positioningClass(), providerListMethodId);
193 jintArray jProviders = jniProvidersObj.object<jintArray>();
194 jint *providers = env->GetIntArrayElements(jProviders, nullptr);
195 const int size = env->GetArrayLength(jProviders);
196 for (int i = 0; i < size; i++) {
197 switch (providers[i]) {
198 case PROVIDER_GPS:
200 break;
201 case PROVIDER_NETWORK:
203 break;
204 case PROVIDER_PASSIVE:
205 //we ignore as Qt doesn't have interface for it right now
206 break;
207 default:
208 __android_log_print(ANDROID_LOG_INFO, logTag, "Unknown positioningMethod");
209 }
210 }
211
212 env->ReleaseIntArrayElements(jProviders, providers, 0);
213
214 return ret;
215 }
216
218 {
220
221 QJniObject jniObject(location);
222 if (!jniObject.isValid())
223 return QGeoPositionInfo();
224
225 const jdouble latitude = jniObject.callMethod<jdouble>("getLatitude");
226 const jdouble longitude = jniObject.callMethod<jdouble>("getLongitude");
227
228 QGeoCoordinate coordinate(latitude, longitude);
229
230 // altitude
231 jboolean attributeExists = jniObject.callMethod<jboolean>("hasAltitude");
232 if (attributeExists) {
233 const jdouble value = jniObject.callMethod<jdouble>("getAltitude");
234 if (!qFuzzyIsNull(value))
235 coordinate.setAltitude(value);
236 }
237
238 info.setCoordinate(coordinate);
239
240 // time stamp
241 const jlong timestamp = jniObject.callMethod<jlong>("getTime");
242 info.setTimestamp(QDateTime::fromMSecsSinceEpoch(timestamp, QTimeZone::UTC));
243
244 // horizontal accuracy
245 attributeExists = jniObject.callMethod<jboolean>("hasAccuracy");
246 if (attributeExists) {
247 const jfloat accuracy = jniObject.callMethod<jfloat>("getAccuracy");
248 if (!qFuzzyIsNull(accuracy))
249 info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, qreal(accuracy));
250 }
251
252 // vertical accuracy (available in API Level 26+)
253 if (QNativeInterface::QAndroidApplication::sdkVersion() > 25) {
254 attributeExists = jniObject.callMethod<jboolean>("hasVerticalAccuracy");
255 if (attributeExists) {
256 const jfloat accuracy = jniObject.callMethod<jfloat>("getVerticalAccuracyMeters");
257 if (!qFuzzyIsNull(accuracy))
258 info.setAttribute(QGeoPositionInfo::VerticalAccuracy, qreal(accuracy));
259 }
260 }
261
262 // ground speed
263 attributeExists = jniObject.callMethod<jboolean>("hasSpeed");
264 if (attributeExists) {
265 const jfloat speed = jniObject.callMethod<jfloat>("getSpeed");
266 if (!qFuzzyIsNull(speed))
267 info.setAttribute(QGeoPositionInfo::GroundSpeed, qreal(speed));
268 }
269
270 // bearing
271 attributeExists = jniObject.callMethod<jboolean>("hasBearing");
272 if (attributeExists) {
273 const jfloat bearing = jniObject.callMethod<jfloat>("getBearing");
274 if (!qFuzzyIsNull(bearing))
275 info.setAttribute(QGeoPositionInfo::Direction, qreal(bearing));
276
277 // bearingAccuracy is available in API Level 26+
278 if (QNativeInterface::QAndroidApplication::sdkVersion() > 25) {
279 const jfloat bearingAccuracy =
280 jniObject.callMethod<jfloat>("getBearingAccuracyDegrees");
281 if (!qFuzzyIsNull(bearingAccuracy))
282 info.setAttribute(QGeoPositionInfo::DirectionAccuracy, qreal(bearingAccuracy));
283 }
284 }
285
286 return info;
287 }
288
290 jobjectArray satellites,
291 QList<QGeoSatelliteInfo>* usedInFix)
292 {
294 jsize length = jniEnv->GetArrayLength(satellites);
295 for (int i = 0; i<length; i++) {
296 jobject element = jniEnv->GetObjectArrayElement(satellites, i);
297 if (QJniEnvironment::checkAndClearExceptions(jniEnv)) {
298 qCWarning(lcPositioning) << "Cannot process all satellite data due to exception.";
299 break;
300 }
301
302 QJniObject jniObj = QJniObject::fromLocalRef(element);
303 if (!jniObj.isValid())
304 continue;
305
307
308 // signal strength
309 const jfloat snr = jniObj.callMethod<jfloat>("getSnr");
310 info.setSignalStrength(int(snr));
311
312 // ignore any satellite with no signal whatsoever
313 if (qFuzzyIsNull(snr))
314 continue;
315
316 // prn
317 const jint prn = jniObj.callMethod<jint>("getPrn");
318 info.setSatelliteIdentifier(prn);
319
320 if (prn >= 1 && prn <= 32)
321 info.setSatelliteSystem(QGeoSatelliteInfo::GPS);
322 else if (prn >= 65 && prn <= 96)
323 info.setSatelliteSystem(QGeoSatelliteInfo::GLONASS);
324 else if (prn >= 193 && prn <= 200)
325 info.setSatelliteSystem(QGeoSatelliteInfo::QZSS);
326 else if ((prn >= 201 && prn <= 235) || (prn >= 401 && prn <= 437))
327 info.setSatelliteSystem(QGeoSatelliteInfo::BEIDOU);
328 else if (prn >= 301 && prn <= 336)
329 info.setSatelliteSystem(QGeoSatelliteInfo::GALILEO);
330
331 // azimuth
332 const jfloat azimuth = jniObj.callMethod<jfloat>("getAzimuth");
333 info.setAttribute(QGeoSatelliteInfo::Azimuth, qreal(azimuth));
334
335 // elevation
336 const jfloat elevation = jniObj.callMethod<jfloat>("getElevation");
337 info.setAttribute(QGeoSatelliteInfo::Elevation, qreal(elevation));
338
339 // Used in fix - true if this satellite is actually used in
340 // determining the position.
341 const jboolean inFix = jniObj.callMethod<jboolean>("usedInFix");
342
343 sats.append(info);
344
345 if (inFix)
346 usedInFix->append(info);
347 }
348
349 return sats;
350 }
351
353 QList<QGeoSatelliteInfo>* usedInFix)
354 {
355 QJniObject jniStatus(gnssStatus);
357
358 const int satellitesCount = jniStatus.callMethod<jint>("getSatelliteCount");
359 for (int i = 0; i < satellitesCount; ++i) {
361
362 // signal strength - this is actually a carrier-to-noise density,
363 // but the values are very close to what was previously returned by
364 // getSnr() method of the GpsSatellite API.
365 const jfloat cn0 = jniStatus.callMethod<jfloat>("getCn0DbHz", i);
366 info.setSignalStrength(static_cast<int>(cn0));
367
368 // satellite system
369 const jint constellationType =
370 jniStatus.callMethod<jint>("getConstellationType", i);
371 info.setSatelliteSystem(ConstellationMapper::toSatelliteSystem(constellationType));
372
373 // satellite identifier
374 const jint svId = jniStatus.callMethod<jint>("getSvid", i);
375 info.setSatelliteIdentifier(svId);
376
377 // azimuth
378 const jfloat azimuth = jniStatus.callMethod<jfloat>("getAzimuthDegrees", i);
379 info.setAttribute(QGeoSatelliteInfo::Azimuth, static_cast<qreal>(azimuth));
380
381 // elevation
382 const jfloat elevation = jniStatus.callMethod<jfloat>("getElevationDegrees", i);
383 info.setAttribute(QGeoSatelliteInfo::Elevation, static_cast<qreal>(elevation));
384
385 // Used in fix - true if this satellite is actually used in
386 // determining the position.
387 const jboolean inFix = jniStatus.callMethod<jboolean>("usedInFix", i);
388
389 sats.append(info);
390
391 if (inFix)
392 usedInFix->append(info);
393 }
394
395 return sats;
396 }
397
398 QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly)
399 {
400 QJniEnvironment env;
401 if (!env.jniEnv())
402 return QGeoPositionInfo();
403
405 return {};
406
407 QJniObject locationObj = QJniObject::callStaticMethod<jobject>(
408 positioningClass(), lastKnownPositionMethodId, fromSatellitePositioningMethodsOnly);
409 jobject location = locationObj.object();
410 if (location == nullptr)
411 return QGeoPositionInfo();
412
414
415 return info;
416 }
417
418 inline int positioningMethodToInt(QGeoPositionInfoSource::PositioningMethods m)
419 {
420 int providerSelection = 0;
422 providerSelection |= 1;
424 providerSelection |= 2;
425
426 return providerSelection;
427 }
428
430 {
431 QJniEnvironment env;
432 if (!env.jniEnv())
434
435 QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
436
437 if (source) {
440
441 int errorCode = QJniObject::callStaticMethod<jint>(
442 positioningClass(), startUpdatesMethodId, androidClassKey,
443 positioningMethodToInt(source->preferredPositioningMethods()),
444 source->updateInterval());
445 switch (errorCode) {
446 case 0:
447 case 1:
448 case 2:
449 case 3:
450 return static_cast<QGeoPositionInfoSource::Error>(errorCode);
451 default:
452 break;
453 }
454 }
455
457 }
458
459 //used for stopping regular and single updates
460 void stopUpdates(int androidClassKey)
461 {
462 QJniObject::callStaticMethod<void>(positioningClass(), stopUpdatesMethodId,
463 androidClassKey);
464 }
465
467 {
468 QJniEnvironment env;
469 if (!env.jniEnv())
471
472 QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
473
474 if (source) {
477
478 int errorCode = QJniObject::callStaticMethod<jint>(
479 positioningClass(), requestUpdateMethodId, androidClassKey,
480 positioningMethodToInt(source->preferredPositioningMethods()),
481 timeout);
482 switch (errorCode) {
483 case 0:
484 case 1:
485 case 2:
486 case 3:
487 return static_cast<QGeoPositionInfoSource::Error>(errorCode);
488 default:
489 break;
490 }
491 }
493 }
494
495 QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int requestTimeout)
496 {
497 QJniEnvironment env;
498 if (!env.jniEnv())
500
501 QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey);
502
503 if (source) {
506
507 int interval = source->updateInterval();
508 if (isSingleRequest)
509 interval = requestTimeout;
510 int errorCode = QJniObject::callStaticMethod<jint>(positioningClass(),
512 androidClassKey, interval,
513 isSingleRequest);
514 switch (errorCode) {
515 case -1:
516 case 0:
517 case 1:
518 case 2:
519 return static_cast<QGeoSatelliteInfoSource::Error>(errorCode);
520 default:
521 qCWarning(lcPositioning)
522 << "startSatelliteUpdates: Unknown error code" << errorCode;
523 break;
524 }
525 }
527 }
528
529
531 {
532 QLocationPermission permission;
533 permission.setAccuracy(QLocationPermission::Precise); // fine location (+ coarse on >= 31)
534
535 // The needed permission depends on whether we run as a service or as an activity
536 if (!QNativeInterface::QAndroidApplication::isActivityContext())
537 permission.setAvailability(QLocationPermission::Always); // background location
538
539 const bool permitted = qApp->checkPermission(permission) == Qt::PermissionStatus::Granted;
540
541 if (!permitted)
542 qCWarning(lcPositioning) << "Position data not available due to missing permission";
543
544 return permitted;
545 }
546}
547
548static void positionUpdated(JNIEnv *env, jobject thiz, QtJniTypes::Location location,
549 jint androidClassKey, jboolean isSingleUpdate)
550{
551 Q_UNUSED(env);
552 Q_UNUSED(thiz);
554
555 QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
556 if (!source) {
557 qCWarning(lcPositioning) << "positionUpdated: source == 0";
558 return;
559 }
560
561 //we need to invoke indirectly as the Looper thread is likely to be not the same thread
562 if (!isSingleUpdate)
563 QMetaObject::invokeMethod(source, "processPositionUpdate", Qt::AutoConnection,
565 else
566 QMetaObject::invokeMethod(source, "processSinglePositionUpdate", Qt::AutoConnection,
568}
569Q_DECLARE_JNI_NATIVE_METHOD(positionUpdated)
570
571static void locationProvidersDisabled(JNIEnv *env, jobject thiz, jint androidClassKey)
572{
573 Q_UNUSED(env);
574 Q_UNUSED(thiz);
575 QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
576 if (!source)
577 source = AndroidPositioning::idToSatSource()->value(androidClassKey);
578 if (!source) {
579 qCWarning(lcPositioning) << "locationProvidersDisabled: source == 0";
580 return;
581 }
582
583 QMetaObject::invokeMethod(source, "locationProviderDisabled", Qt::AutoConnection);
584}
585Q_DECLARE_JNI_NATIVE_METHOD(locationProvidersDisabled)
586
587static void locationProvidersChanged(JNIEnv *env, jobject thiz, jint androidClassKey)
588{
589 Q_UNUSED(env);
590 Q_UNUSED(thiz);
591 QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
592 if (!source) {
593 qCWarning(lcPositioning) << "locationProvidersChanged: source == 0";
594 return;
595 }
596
597 QMetaObject::invokeMethod(source, "locationProvidersChanged", Qt::AutoConnection);
598}
599Q_DECLARE_JNI_NATIVE_METHOD(locationProvidersChanged)
600
602 const QList<QGeoSatelliteInfo> &inUse,
603 jint androidClassKey, jboolean isSingleUpdate)
604{
605 QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey);
606 if (!source) {
607 qCWarning(lcPositioning) << "notifySatelliteInfoUpdated: source == 0";
608 return;
609 }
610
611 QMetaObject::invokeMethod(source, "processSatelliteUpdate", Qt::AutoConnection,
614 Q_ARG(bool, isSingleUpdate));
615}
616
617static void satelliteGpsUpdated(JNIEnv *env, jobject thiz,
618 jobjectArray satellites,
619 jint androidClassKey, jboolean isSingleUpdate)
620{
621 Q_UNUSED(thiz);
625
626 notifySatelliteInfoUpdated(sats, inUse, androidClassKey, isSingleUpdate);
627}
628Q_DECLARE_JNI_NATIVE_METHOD(satelliteGpsUpdated)
629
630static void satelliteGnssUpdated(JNIEnv *env, jobject thiz, QtJniTypes::GnssStatus gnssStatus,
631 jint androidClassKey, jboolean isSingleUpdate)
632{
633 Q_UNUSED(env);
634 Q_UNUSED(thiz);
635
639
640 notifySatelliteInfoUpdated(sats, inUse, androidClassKey, isSingleUpdate);
641}
642Q_DECLARE_JNI_NATIVE_METHOD(satelliteGnssUpdated)
643
644#define GET_AND_CHECK_STATIC_METHOD(VAR, METHOD_NAME, ...) \
645 VAR = env.findStaticMethod<__VA_ARGS__>(positioningClass(), METHOD_NAME); \
646 if (!VAR) { \
647 __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, \
648 QtJniTypes::methodSignature<__VA_ARGS__>().data()); \
649 return false; \
650 }
651
652static bool registerNatives()
653{
654 QJniEnvironment env;
655 if (!env.jniEnv()) {
656 __android_log_print(ANDROID_LOG_FATAL, logTag, "Failed to create environment");
657 return false;
658 }
659
660 if (!positioningClass.init()) {
661 __android_log_print(ANDROID_LOG_FATAL, logTag, "Failed to create global class ref");
662 return false;
663 }
664
665 if (!env.registerNativeMethods(positioningClass(), {
666 Q_JNI_NATIVE_METHOD(positionUpdated),
667 Q_JNI_NATIVE_METHOD(locationProvidersDisabled),
668 Q_JNI_NATIVE_METHOD(satelliteGpsUpdated),
669 Q_JNI_NATIVE_METHOD(locationProvidersChanged),
670 Q_JNI_NATIVE_METHOD(satelliteGnssUpdated)
671 })) {
672 __android_log_print(ANDROID_LOG_FATAL, logTag, "Failed to register native methods");
673 return false;
674 }
675
676 GET_AND_CHECK_STATIC_METHOD(providerListMethodId, "providerList", jintArray);
678 QtJniTypes::Location, bool);
679 GET_AND_CHECK_STATIC_METHOD(startUpdatesMethodId, "startUpdates", jint, jint, jint, jint);
680 GET_AND_CHECK_STATIC_METHOD(stopUpdatesMethodId, "stopUpdates", void, jint);
681 GET_AND_CHECK_STATIC_METHOD(requestUpdateMethodId, "requestUpdate", jint, jint, jint, jint);
683 jint, jint, jint, bool);
684
685 return true;
686}
687
688Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM * /*vm*/, void * /*reserved*/)
689{
690 static bool initialized = false;
691 if (initialized)
692 return JNI_VERSION_1_6;
693 initialized = true;
694
695 __android_log_print(ANDROID_LOG_INFO, logTag, "Positioning start");
696
697 if (!registerNatives()) {
698 __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives() failed");
699 return -1;
700 }
701
702 if (!ConstellationMapper::init()) {
703 __android_log_print(ANDROID_LOG_ERROR, logTag,
704 "Failed to extract constellation type constants. "
705 "Satellite system will be undefined!");
706 }
707
708 return JNI_VERSION_1_6;
709}
710
GlobalClassRefWrapper()=default
static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
\inmodule QtPositioning
Error
The Error enumeration represents the errors which can occur.
\inmodule QtPositioning
Error
The Error enumeration represents the errors which can occur.
\inmodule QtPositioning
SatelliteSystem
Defines the GNSS system of the satellite.
\inmodule QtCore
\inmodule QtCore
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
Access the user's location.
Q_CORE_EXPORT void setAvailability(Availability availability)
Sets the desired availability of the request.
Q_CORE_EXPORT void setAccuracy(Accuracy accuracy)
Sets the desired accuracy of the request.
Definition qmap.h:186
\inmodule QtCore
Definition qobject.h:90
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
static const char logTag[]
static jmethodID providerListMethodId
#define GET_AND_CHECK_STATIC_METHOD(VAR, METHOD_NAME,...)
static jmethodID requestUpdateMethodId
static void positionUpdated(JNIEnv *env, jobject thiz, QtJniTypes::Location location, jint androidClassKey, jboolean isSingleUpdate)
static jmethodID startSatelliteUpdatesMethodId
static const char logTag[]
static jmethodID stopUpdatesMethodId
static jmethodID startUpdatesMethodId
static void notifySatelliteInfoUpdated(const QList< QGeoSatelliteInfo > &inView, const QList< QGeoSatelliteInfo > &inUse, jint androidClassKey, jboolean isSingleUpdate)
static GlobalClassRefWrapper< QtJniTypes::QtPositioning > positioningClass
static void satelliteGpsUpdated(JNIEnv *env, jobject thiz, jobjectArray satellites, jint androidClassKey, jboolean isSingleUpdate)
static jmethodID lastKnownPositionMethodId
static const char methodErrorMsg[]
static void satelliteGnssUpdated(JNIEnv *env, jobject thiz, QtJniTypes::GnssStatus gnssStatus, jint androidClassKey, jboolean isSingleUpdate)
static void locationProvidersChanged(JNIEnv *env, jobject thiz, jint androidClassKey)
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *)
static void locationProvidersDisabled(JNIEnv *env, jobject thiz, jint androidClassKey)
static bool registerNatives()
void unregisterPositionInfoSource(int key)
QList< QGeoSatelliteInfo > satelliteInfoFromJavaGnssStatus(jobject gnssStatus, QList< QGeoSatelliteInfo > *usedInFix)
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly)
QMap< int, QGeoPositionInfoSourceAndroid * > PositionSourceMap
QMap< int, QGeoSatelliteInfoSourceAndroid * > SatelliteSourceMap
QGeoPositionInfo positionInfoFromJavaLocation(const jobject &location)
int positioningMethodToInt(QGeoPositionInfoSource::PositioningMethods m)
QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int requestTimeout)
QList< QGeoSatelliteInfo > satelliteInfoFromJavaLocation(JNIEnv *jniEnv, jobjectArray satellites, QList< QGeoSatelliteInfo > *usedInFix)
int registerPositionInfoSource(QObject *obj)
QGeoPositionInfoSource::Error requestUpdate(int androidClassKey, int timeout)
QGeoPositionInfoSource::Error startUpdates(int androidClassKey)
QGeoPositionInfoSource::PositioningMethods availableProviders()
void stopUpdates(int androidClassKey)
@ AutoConnection
#define Q_DECL_EXPORT
#define qApp
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
return ret
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
#define Q_ARG(Type, data)
Definition qobjectdefs.h:62
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLint location
const GLfloat * m
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLbitfield GLuint64 timeout
[4]
GLenum src
GLsizei GLsizei GLchar * source
GLhandleARB obj
[2]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE Q_DECLARE_JNI_CLASS(Environment, "android/os/Environment")
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
QFileInfo info(fileName)
[8]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...