From 594ec018648060340bfbd96477cfd743d7133a56 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Mon, 27 Jan 2020 16:57:01 +0200 Subject: Android: request permissions before location requests or updates startSatelliteUpdates() and lastKnownPosition() were not checking Android permissions before trying to access positioning data. Task-number: QTBUG-81689 Change-Id: Ia4d75920b7b07c6782d80a483a3e3961ed9149f5 Reviewed-by: Alex Blasche --- .../position/android/src/jnipositioning.cpp | 60 ++++++++++++---------- src/plugins/position/android/src/jnipositioning.h | 2 + src/positioning/positioning.pro | 4 +- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp index 4812e307..05b25d98 100644 --- a/src/plugins/position/android/src/jnipositioning.cpp +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include #include "qgeopositioninfosource_android_p.h" #include "qgeosatelliteinfosource_android_p.h" @@ -351,6 +350,9 @@ namespace AndroidPositioning { if (!env.jniEnv) return QGeoPositionInfo(); + if (!requestionPositioningPermissions(env.jniEnv)) + return {}; + jobject location = env.jniEnv->CallStaticObjectMethod(positioningClass, lastKnownPositionMethodId, fromSatellitePositioningMethodsOnly); @@ -383,19 +385,8 @@ namespace AndroidPositioning { QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); if (source) { - // Android v23+ requires runtime permission check and requests - QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION")); - - if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) { - const QHash results = - QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission); - if (!results.contains(permission) - || results[permission] == QtAndroidPrivate::PermissionsResult::Denied) - { - qWarning() << "Position retrieval not possible due to missing permission (ACCESS_FINE_LOCATION)"; - return QGeoPositionInfoSource::AccessError; - } - } + if (!requestionPositioningPermissions(env.jniEnv)) + return QGeoPositionInfoSource::AccessError; int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId, androidClassKey, @@ -434,19 +425,8 @@ namespace AndroidPositioning { QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); if (source) { - // Android v23+ requires runtime permission check and requests - QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION")); - - if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) { - const QHash results = - QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission); - if (!results.contains(permission) - || results[permission] == QtAndroidPrivate::PermissionsResult::Denied) - { - qWarning() << "Position update not possible due to missing permission (ACCESS_FINE_LOCATION)"; - return QGeoPositionInfoSource::AccessError; - } - } + if (!requestionPositioningPermissions(env.jniEnv)) + return QGeoPositionInfoSource::AccessError; int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId, androidClassKey, @@ -473,6 +453,9 @@ namespace AndroidPositioning { QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); if (source) { + if (!requestionPositioningPermissions(env.jniEnv)) + return QGeoSatelliteInfoSource::AccessError; + int interval = source->updateInterval(); if (isSingleRequest) interval = requestTimeout; @@ -492,8 +475,29 @@ namespace AndroidPositioning { } return QGeoSatelliteInfoSource::UnknownSourceError; } -} + bool requestionPositioningPermissions(JNIEnv *env) + { + using namespace QtAndroidPrivate; + + if (androidSdkVersion() < 23) + return true; + + // Android v23+ requires runtime permission check and requests + QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION")); + + if (checkPermission(permission) == PermissionsResult::Denied) { + const QHash results = + requestPermissionsSync(env, QStringList() << permission); + if (!results.contains(permission) || results[permission] == PermissionsResult::Denied) { + qWarning() << "Position data not available due to missing permission " << permission; + return false; + } + } + + return true; + } +} static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jint androidClassKey, jboolean isSingleUpdate) { diff --git a/src/plugins/position/android/src/jnipositioning.h b/src/plugins/position/android/src/jnipositioning.h index 0de6a5aa..0c051b8c 100644 --- a/src/plugins/position/android/src/jnipositioning.h +++ b/src/plugins/position/android/src/jnipositioning.h @@ -40,6 +40,7 @@ #ifndef JNIPOSITIONING_H #define JNIPOSITIONING_H +#include #include #include @@ -58,6 +59,7 @@ namespace AndroidPositioning QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int updateRequestTimeout); + bool requestionPositioningPermissions(JNIEnv *env); } #endif // JNIPOSITIONING_H diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 06e2d531..65350909 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -11,8 +11,10 @@ OTHER_FILES += configure.json doc/src/*.qdoc doc/src/plugins/*.qdoc # show .qd ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning -ANDROID_PERMISSIONS = \ +ANDROID_PERMISSIONS += \ android.permission.ACCESS_FINE_LOCATION +ANDROID_FEATURES += \ + android.hardware.location.gps ANDROID_LIB_DEPENDENCIES = \ plugins/position/libplugins_position_qtposition_android.so MODULE_WINRT_CAPABILITIES_DEVICE += \ -- cgit v1.2.1