Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update samples to request permissions #1753

Merged
merged 15 commits into from
Oct 23, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include "MapViewTypes.h"
#include "PortalItem.h"

#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) || defined(Q_OS_IOS) || defined(Q_OS_MACOS) || defined(Q_OS_ANDROID)
#define PERMISSIONS_PLATFORM
#endif

using namespace Esri::ArcGISRuntime;

namespace {
Expand Down Expand Up @@ -79,11 +83,50 @@ void ShowDeviceLocationUsingIndoorPositioning::setMapView(MapQuickView* mapView)
m_mapView = mapView;
m_mapView->setMap(m_map);

setupIndoorsLocationDataSource();
#ifdef PERMISSIONS_PLATFORM
requestBluetoothThenLocationPermissions();
#else
setupIndoorsLocationDataSource();
#endif

emit mapViewChanged();
}

void ShowDeviceLocationUsingIndoorPositioning::requestBluetoothThenLocationPermissions()
{
qApp->requestPermission(QBluetoothPermission{}, [this](const QPermission& permission)
{
Q_UNUSED(permission);
requestLocationPermissionThenSetupILDS();
});
}

void ShowDeviceLocationUsingIndoorPositioning::requestLocationPermissionThenSetupILDS()
{
QLocationPermission locationPermission{};
locationPermission.setAccuracy(QLocationPermission::Accuracy::Precise);
locationPermission.setAvailability(QLocationPermission::Availability::WhenInUse);
qApp->requestPermission(locationPermission, [this](const QPermission& permission)
{
Q_UNUSED(permission);
checkPermissions();
setupIndoorsLocationDataSource();
});
}

void ShowDeviceLocationUsingIndoorPositioning::checkPermissions()
{
if (qApp->checkPermission(QBluetoothPermission{}) == Qt::PermissionStatus::Denied)
{
emit bluetoothPermissionDenied();
}

if (qApp->checkPermission(QLocationPermission{}) == Qt::PermissionStatus::Denied)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (qApp->checkPermission(QLocationPermission{}) == Qt::PermissionStatus::Denied)
QLocationPermission locationPermission{};
locationPermission.setAccuracy(QLocationPermission::Accuracy::Precise);
locationPermission.setAvailability(QLocationPermission::Availability::WhenInUse);
if (qApp->checkPermission(locationPermission) == Qt::PermissionStatus::Denied)

A default instantiated QLocationPermission has Accuracy::Approximate on macOS. We requested Accuracy::Precise in requestLocationPermissionThenSetupILDS, so best to check that we got it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are the accuracy and availability parameters checked here? The checkPermission only checks the status right?

Copy link
Collaborator

@bri12415 bri12415 Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't explicitly state which types of Accuracy and Availability you are checking on the QLocationPermission passed into checkPermission(), you'll be checking the permission status of Accuracy::Approximate and Availability::WhenInUse (on macOS).

But you requested Accuracy::Precise and Availability::WhenInUse, because that is what is needed by ILDS.

So what could go wrong with the current code is that you request Accuracy::Precise, but the user only provides Accuracy::Approximate. And because you are only checking Accuracy::Approximate, the permission check passes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

{
emit locationPermissionDenied();
}
}

// This function uses a helper class `IndoorsLocationDataSourceCreator` to construct the IndoorsLocationDataSource
void ShowDeviceLocationUsingIndoorPositioning::setupIndoorsLocationDataSource()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
// Qt headers
#include <QMap>
#include <QObject>
#include <QPermissions>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be here anymore. Should be in ShowDeviceLocationUsingIndoorPositioning.cpp

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added to cpp file


namespace Esri::ArcGISRuntime
{
Expand Down Expand Up @@ -52,6 +53,8 @@ class ShowDeviceLocationUsingIndoorPositioning : public QObject
signals:
void mapViewChanged();
void locationPropertiesChanged();
void locationPermissionDenied();
void bluetoothPermissionDenied();

private:
Esri::ArcGISRuntime::MapQuickView* mapView() const;
Expand All @@ -61,6 +64,9 @@ class ShowDeviceLocationUsingIndoorPositioning : public QObject
void setupIndoorsLocationDataSource();
void locationChangedHandler(const Esri::ArcGISRuntime::Location& loc);
void changeFloorDisplay();
void requestLocationPermissionThenSetupILDS();
void requestBluetoothThenLocationPermissions();
void checkPermissions();

Esri::ArcGISRuntime::Map* m_map = nullptr;
Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ ios {
OTHER_FILES += \
$$PWD/Info.plist

QMAKE_INFO_PLIST = $$PWD/Info.plist
QMAKE_INFO_PLIST = $$PWD/ios/Info.plist
}

macx {
QMAKE_INFO_PLIST = $$PWD/mac/Info.plist
}

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Esri.Samples
import QtQuick.Dialogs

Item {

Expand Down Expand Up @@ -80,4 +81,46 @@ Item {
id: model
mapView: view
}

Connections {
target: model
function onLocationPermissionDenied() {
locationPermissionDeniedDialog.open()
}
}

Dialog {
id: locationPermissionDeniedDialog
title: "Location Permission Denied"
modal: true
standardButtons: Dialog.Ok
x: (parent.width - width) / 2
y: (parent.height - height) / 2

Text {
text: "This application requires location permission."
color: "white"
}
}

Connections {
target: model
function onBluetoothPermissionDenied() {
bluetoothPermissionDeniedDialog.open()
}
}

Dialog {
id: bluetoothPermissionDeniedDialog
title: "Bluetooth Permission Denied"
modal: true
standardButtons: Dialog.Ok
x: (parent.width - width) / 2
y: (parent.height - height) / 2

Text {
text: "This application requires bluetooth permission."
color: "white"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>ShowDeviceLocationUsingIndoorPositioning</string>
<key>CFBundleExecutable</key>
<string>ShowDeviceLocationUsingIndoorPositioning</string>
<key>CFBundleGetInfoString</key>
<string>ArcGIS</string>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
<string>com.esri.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NOTE</key>
<string>This app is cool</string>
<key>UIFileSharingEnabled</key>
<string>FALSE</string>
<key>UIRequiresPersistentWiFi</key>
<string>NO</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location required for application</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Location required for application</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Bluetooth access is required for Indoor Positioning</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>FindPlace</string>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these will need to be changed to ShowDeviceLocationUsingIndoorPositioning

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

<key>CFBundleExecutable</key>
<string>FindPlace</string>
<key>CFBundleGetInfoString</key>
<string>ArcGIS</string>
<key>CFBundleIdentifier</key>
<string>com.esri.FindPlace</string>
<key>CFBundleName</key>
<string>FindPlace</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSLocationUsageDescription</key>
<string>Location required for application</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location required for application</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Location required for application</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Bluetooth access is required for Indoor Positioning</string>
</dict>
</plist>

28 changes: 28 additions & 0 deletions CppSamples/Search/FindPlace/FindPlace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
#include <QUrl>
#include <QUuid>

#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) || defined(Q_OS_IOS) || defined(Q_OS_MACOS) || defined(Q_OS_ANDROID)
#define PERMISSIONS_PLATFORM
#include <QPermissions>
#endif

using namespace Esri::ArcGISRuntime;

FindPlace::FindPlace(QQuickItem* parent /* = nullptr */):
Expand Down Expand Up @@ -96,6 +101,9 @@ void FindPlace::componentComplete()
m_mapView->calloutData()->setVisible(false);
m_calloutData = m_mapView->calloutData();

// start location permission
startLocationPermission();

// connect mapview signals
connectSignals();
}
Expand Down Expand Up @@ -143,6 +151,26 @@ void FindPlace::connectSignals()
});
}

void FindPlace::startLocationPermission()
{
#ifdef PERMISSIONS_PLATFORM
QLocationPermission locationPermission{};
locationPermission.setAccuracy(QLocationPermission::Accuracy::Precise);
locationPermission.setAvailability(QLocationPermission::Availability::WhenInUse);
switch (qApp->checkPermission(locationPermission))
{
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(locationPermission, this, &FindPlace::startLocationPermission);
return;
case Qt::PermissionStatus::Granted:
return;
case Qt::PermissionStatus::Denied:
emit locationPermissionDenied();
return;
}
#endif
}

void FindPlace::addGraphicsOverlay()
{
// add a graphics overlay to the mapview
Expand Down
2 changes: 2 additions & 0 deletions CppSamples/Search/FindPlace/FindPlace.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class FindPlace : public QQuickItem
void hideCallout();
void showCallout();
void showExtentButton();
void locationPermissionDenied();

private:
void addGraphicsOverlay();
Expand All @@ -78,6 +79,7 @@ class FindPlace : public QQuickItem
void setPoiTextHasFocus(bool hasFocus);
Esri::ArcGISRuntime::GeocodeParameters createParameters();
void onGeocodingCompleted_(const QList<Esri::ArcGISRuntime::GeocodeResult>& results);
void startLocationPermission();

private:
Esri::ArcGISRuntime::Map* m_map = nullptr;
Expand Down
6 changes: 5 additions & 1 deletion CppSamples/Search/FindPlace/FindPlace.pro
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ ios {
OTHER_FILES += \
$$PWD/Info.plist

QMAKE_INFO_PLIST = $$PWD/Info.plist
QMAKE_INFO_PLIST = $$PWD/ios/Info.plist
}

macx {
QMAKE_INFO_PLIST = $$PWD/mac/Info.plist
}

android {
Expand Down
22 changes: 22 additions & 0 deletions CppSamples/Search/FindPlace/FindPlace.qml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import QtQuick.Controls
import QtPositioning
import Esri.ArcGISRuntime.Toolkit
import Esri.Samples
import QtQuick.Dialogs

FindPlaceSample {
id: findPlaceSample
Expand Down Expand Up @@ -151,4 +152,25 @@ FindPlaceSample {
callout.dismiss();
}
}

Connections {
target: findPlaceSample
function onLocationPermissionDenied() {
permissionDeniedDialog.open()
}
}

Dialog {
id: permissionDeniedDialog
title: "Location Permission Denied"
modal: true
standardButtons: Dialog.Ok
x: (parent.width - width) / 2
y: (parent.height - height) / 2

Text {
text: "This application requires location permissions."
color: "white"
}
}
}
Loading