From e09a25a24e7f834c91d383e27b4546b0cda42fe8 Mon Sep 17 00:00:00 2001
From: Alex Blasche <alexander.blasche@qt.io>
Date: Wed, 14 Sep 2016 12:12:09 +0200
Subject: [PATCH] Add capability to ask for Location permission at runtime

This is required since Android v23+.

Task-number: QTBUG-55988
Change-Id: I41777cfbb6fde38dc0f8045c9320f420bb0b43a2
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
---
 .../position/android/src/jnipositioning.cpp   | 29 +++++++++++++++++++
 src/plugins/position/android/src/src.pro      |  2 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp
index e0124eb6b..547d0fadf 100644
--- a/src/plugins/position/android/src/jnipositioning.cpp
+++ b/src/plugins/position/android/src/jnipositioning.cpp
@@ -41,6 +41,7 @@
 #include <QDebug>
 #include <QMap>
 #include <QtGlobal>
+#include <QtCore/private/qjnihelpers_p.h>
 #include <android/log.h>
 #include <jni.h>
 #include <QGeoPositionInfo>
@@ -367,6 +368,20 @@ 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<QString, QtAndroidPrivate::PermissionsResult> 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;
+                }
+            }
+
             int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId,
                                              androidClassKey,
                                              positioningMethodToInt(source->preferredPositioningMethods()),
@@ -404,6 +419,20 @@ 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<QString, QtAndroidPrivate::PermissionsResult> 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;
+                }
+            }
+
             int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId,
                                              androidClassKey,
                                              positioningMethodToInt(source->preferredPositioningMethods()));
diff --git a/src/plugins/position/android/src/src.pro b/src/plugins/position/android/src/src.pro
index 3a19c85e7..36facc55b 100644
--- a/src/plugins/position/android/src/src.pro
+++ b/src/plugins/position/android/src/src.pro
@@ -1,6 +1,6 @@
 TARGET = qtposition_android
 
-QT = core positioning
+QT = core core-private positioning
 
 HEADERS = \
     positionfactory_android.h \
-- 
GitLab