Update permission handling
This commit is contained in:
parent
a5bea39212
commit
b847d5ba59
@ -227,7 +227,7 @@ public class NymeaAppControlService extends ControlsProviderService {
|
|||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||||
intent.putExtra("nymeaId", nymeaId.toString());
|
intent.putExtra("nymeaId", nymeaId.toString());
|
||||||
intent.putExtra("thingId", thing.id.toString());
|
intent.putExtra("thingId", thing.id.toString());
|
||||||
pi = PendingIntent.getActivity(context, intentId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
pi = PendingIntent.getActivity(context, intentId, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
Log.d(TAG, "Created pendingintent for " + thing.name + " with id " + intentId + " and extra " + thing.id);
|
Log.d(TAG, "Created pendingintent for " + thing.name + " with id " + intentId + " and extra " + thing.id);
|
||||||
|
|
||||||
Control.StatefulBuilder builder = new Control.StatefulBuilder(thing.id.toString(), pi)
|
Control.StatefulBuilder builder = new Control.StatefulBuilder(thing.id.toString(), pi)
|
||||||
|
|||||||
@ -36,7 +36,6 @@
|
|||||||
#include "thingmanager.h"
|
#include "thingmanager.h"
|
||||||
#include "connection/nymeatransportinterface.h"
|
#include "connection/nymeatransportinterface.h"
|
||||||
#include "jsonrpc/jsonrpcclient.h"
|
#include "jsonrpc/jsonrpcclient.h"
|
||||||
#include "wifisetup/bluetoothdiscovery.h"
|
|
||||||
|
|
||||||
class RuleManager;
|
class RuleManager;
|
||||||
class ScriptManager;
|
class ScriptManager;
|
||||||
|
|||||||
@ -73,6 +73,8 @@
|
|||||||
#include "configuration/serverconfigurations.h"
|
#include "configuration/serverconfigurations.h"
|
||||||
#include "configuration/mqttpolicy.h"
|
#include "configuration/mqttpolicy.h"
|
||||||
#include "configuration/mqttpolicies.h"
|
#include "configuration/mqttpolicies.h"
|
||||||
|
#include "wifisetup/bluetoothdeviceinfos.h"
|
||||||
|
#include "wifisetup/bluetoothdiscovery.h"
|
||||||
#include "wifisetup/btwifisetup.h"
|
#include "wifisetup/btwifisetup.h"
|
||||||
#include "types/wirelessaccesspoint.h"
|
#include "types/wirelessaccesspoint.h"
|
||||||
#include "types/wirelessaccesspoints.h"
|
#include "types/wirelessaccesspoints.h"
|
||||||
|
|||||||
@ -45,6 +45,7 @@
|
|||||||
#include "nfchelper.h"
|
#include "nfchelper.h"
|
||||||
#include "nfcthingactionwriter.h"
|
#include "nfcthingactionwriter.h"
|
||||||
#include "platformhelper.h"
|
#include "platformhelper.h"
|
||||||
|
#include "platformintegration/platformpermissions.h"
|
||||||
#include "dashboard/dashboardmodel.h"
|
#include "dashboard/dashboardmodel.h"
|
||||||
#include "dashboard/dashboarditem.h"
|
#include "dashboard/dashboarditem.h"
|
||||||
#include "mouseobserver.h"
|
#include "mouseobserver.h"
|
||||||
@ -169,6 +170,7 @@ int main(int argc, char *argv[])
|
|||||||
engine->rootContext()->setContextProperty("styleController", &styleController);
|
engine->rootContext()->setContextProperty("styleController", &styleController);
|
||||||
|
|
||||||
qmlRegisterSingletonType<PlatformHelper>("Nymea", 1, 0, "PlatformHelper", PlatformHelper::platformHelperProvider);
|
qmlRegisterSingletonType<PlatformHelper>("Nymea", 1, 0, "PlatformHelper", PlatformHelper::platformHelperProvider);
|
||||||
|
qmlRegisterSingletonType<PlatformPermissions>("Nymea", 1, 0, "PlatformPermissions", PlatformPermissions::qmlProvider);
|
||||||
qmlRegisterSingletonType<NfcHelper>("Nymea", 1, 0, "NfcHelper", NfcHelper::nfcHelperProvider);
|
qmlRegisterSingletonType<NfcHelper>("Nymea", 1, 0, "NfcHelper", NfcHelper::nfcHelperProvider);
|
||||||
qmlRegisterType<NfcThingActionWriter>("Nymea", 1, 0, "NfcThingActionWriter");
|
qmlRegisterType<NfcThingActionWriter>("Nymea", 1, 0, "NfcThingActionWriter");
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ HEADERS += \
|
|||||||
nfchelper.h \
|
nfchelper.h \
|
||||||
nfcthingactionwriter.h \
|
nfcthingactionwriter.h \
|
||||||
platformintegration/generic/screenhelper.h \
|
platformintegration/generic/screenhelper.h \
|
||||||
|
platformintegration/platformpermissions.h \
|
||||||
stylecontroller.h \
|
stylecontroller.h \
|
||||||
pushnotifications.h \
|
pushnotifications.h \
|
||||||
platformhelper.h \
|
platformhelper.h \
|
||||||
@ -39,6 +40,7 @@ SOURCES += main.cpp \
|
|||||||
mouseobserver.cpp \
|
mouseobserver.cpp \
|
||||||
nfchelper.cpp \
|
nfchelper.cpp \
|
||||||
nfcthingactionwriter.cpp \
|
nfcthingactionwriter.cpp \
|
||||||
|
platformintegration/platformpermissions.cpp \
|
||||||
stylecontroller.cpp \
|
stylecontroller.cpp \
|
||||||
pushnotifications.cpp \
|
pushnotifications.cpp \
|
||||||
platformhelper.cpp \
|
platformhelper.cpp \
|
||||||
@ -73,11 +75,14 @@ android {
|
|||||||
include(../3rdParty/android/android_openssl/openssl.pri)
|
include(../3rdParty/android/android_openssl/openssl.pri)
|
||||||
|
|
||||||
ANDROID_MIN_SDK_VERSION = 21
|
ANDROID_MIN_SDK_VERSION = 21
|
||||||
ANDROID_TARGET_SDK_VERSION = 31
|
ANDROID_TARGET_SDK_VERSION = 33
|
||||||
|
|
||||||
QT += androidextras
|
QT += androidextras
|
||||||
HEADERS += platformintegration/android/platformhelperandroid.h
|
HEADERS += platformintegration/android/platformhelperandroid.h \
|
||||||
SOURCES += platformintegration/android/platformhelperandroid.cpp
|
platformintegration/android/platformpermissionsandroid.h \
|
||||||
|
|
||||||
|
SOURCES += platformintegration/android/platformhelperandroid.cpp \
|
||||||
|
platformintegration/android/platformpermissionsandroid.cpp \
|
||||||
|
|
||||||
# https://bugreports.qt.io/browse/QTBUG-83165
|
# https://bugreports.qt.io/browse/QTBUG-83165
|
||||||
LIBS += -L$${top_builddir}/libnymea-app/$${ANDROID_TARGET_ARCH}
|
LIBS += -L$${top_builddir}/libnymea-app/$${ANDROID_TARGET_ARCH}
|
||||||
@ -131,13 +136,20 @@ macx: {
|
|||||||
|
|
||||||
ios: {
|
ios: {
|
||||||
message("iOS build")
|
message("iOS build")
|
||||||
HEADERS += platformintegration/ios/platformhelperios.h
|
HEADERS += platformintegration/ios/platformhelperios.h \
|
||||||
SOURCES += platformintegration/ios/platformhelperios.cpp
|
platformintegration/ios/platformpermissionsios.h \
|
||||||
|
|
||||||
|
SOURCES += platformintegration/ios/platformhelperios.cpp \
|
||||||
|
platformintegration/ios/platformpermissionsios.cpp \
|
||||||
|
|
||||||
OBJECTIVE_SOURCES += platformintegration/ios/platformhelperios.mm \
|
OBJECTIVE_SOURCES += platformintegration/ios/platformhelperios.mm \
|
||||||
platformintegration/ios/pushnotifications.mm \
|
platformintegration/ios/pushnotifications.mm \
|
||||||
|
platformintegration/ios/platformpermissionsios.mm \
|
||||||
|
|
||||||
OTHER_FILES += $${OBJECTIVE_SOURCES}
|
OTHER_FILES += $${OBJECTIVE_SOURCES}
|
||||||
|
|
||||||
|
LIBS += -framework CoreLocation \
|
||||||
|
|
||||||
# Add Firebase SDK
|
# Add Firebase SDK
|
||||||
QMAKE_LFLAGS += -ObjC $(inherited)
|
QMAKE_LFLAGS += -ObjC $(inherited)
|
||||||
firebase_files.files += $$files($${IOS_PACKAGE_DIR}/GoogleService-Info.plist)
|
firebase_files.files += $$files($${IOS_PACKAGE_DIR}/GoogleService-Info.plist)
|
||||||
|
|||||||
@ -99,16 +99,6 @@ PlatformHelper *PlatformHelper::instance(bool create)
|
|||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformHelper::hasPermissions() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformHelper::requestPermissions()
|
|
||||||
{
|
|
||||||
emit permissionsRequestFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformHelper::hideSplashScreen()
|
void PlatformHelper::hideSplashScreen()
|
||||||
{
|
{
|
||||||
setSplashVisible(false);
|
setSplashVisible(false);
|
||||||
|
|||||||
@ -43,7 +43,6 @@ class QJSEngine;
|
|||||||
class PlatformHelper : public QObject
|
class PlatformHelper : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool hasPermissions READ hasPermissions NOTIFY permissionsRequestFinished)
|
|
||||||
Q_PROPERTY(QString platform READ platform CONSTANT)
|
Q_PROPERTY(QString platform READ platform CONSTANT)
|
||||||
Q_PROPERTY(QString deviceSerial READ deviceSerial CONSTANT)
|
Q_PROPERTY(QString deviceSerial READ deviceSerial CONSTANT)
|
||||||
Q_PROPERTY(QString device READ device CONSTANT)
|
Q_PROPERTY(QString device READ device CONSTANT)
|
||||||
@ -70,9 +69,6 @@ public:
|
|||||||
static PlatformHelper* instance(bool create = true);
|
static PlatformHelper* instance(bool create = true);
|
||||||
virtual ~PlatformHelper() = default;
|
virtual ~PlatformHelper() = default;
|
||||||
|
|
||||||
virtual bool hasPermissions() const;
|
|
||||||
Q_INVOKABLE virtual void requestPermissions();
|
|
||||||
|
|
||||||
virtual QString platform() const;
|
virtual QString platform() const;
|
||||||
virtual QString machineHostname() const;
|
virtual QString machineHostname() const;
|
||||||
virtual QString device() const;
|
virtual QString device() const;
|
||||||
@ -113,7 +109,6 @@ public:
|
|||||||
void notificationActionReceived(const QString &nymeaData);
|
void notificationActionReceived(const QString &nymeaData);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void permissionsRequestFinished();
|
|
||||||
void screenTimeoutChanged();
|
void screenTimeoutChanged();
|
||||||
void screenBrightnessChanged();
|
void screenBrightnessChanged();
|
||||||
void topPanelColorChanged();
|
void topPanelColorChanged();
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public class NymeaAppNotificationService extends FirebaseMessagingService {
|
|||||||
intent.setAction(Intent.ACTION_SEND);
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
intent.putExtra("notificationData", remoteMessage.getData().get("nymeaData"));
|
intent.putExtra("notificationData", remoteMessage.getData().get("nymeaData"));
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||||
|
|
||||||
// We can't directly access R.drawable.notificationicon from here:
|
// We can't directly access R.drawable.notificationicon from here:
|
||||||
// When the package is branded, the package name is not "io.guh.nymeaapp" and resources in
|
// When the package is branded, the package name is not "io.guh.nymeaapp" and resources in
|
||||||
@ -83,7 +83,7 @@ public class NymeaAppNotificationService extends FirebaseMessagingService {
|
|||||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
NotificationChannel channel = new NotificationChannel("notify_001", "Channel human readable title", NotificationManager.IMPORTANCE_HIGH);
|
NotificationChannel channel = new NotificationChannel("notify_001", "Notifications from your nymea system", NotificationManager.IMPORTANCE_HIGH);
|
||||||
notificationManager.createNotificationChannel(channel);
|
notificationManager.createNotificationChannel(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -84,11 +84,6 @@ PlatformHelperAndroid::PlatformHelperAndroid(QObject *parent) : PlatformHelper(p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformHelperAndroid::requestPermissions()
|
|
||||||
{
|
|
||||||
// Not using any fancy permissions in android yet...
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformHelperAndroid::hideSplashScreen()
|
void PlatformHelperAndroid::hideSplashScreen()
|
||||||
{
|
{
|
||||||
// Android's splash will flicker when fading out twice
|
// Android's splash will flicker when fading out twice
|
||||||
@ -99,12 +94,6 @@ void PlatformHelperAndroid::hideSplashScreen()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformHelperAndroid::hasPermissions() const
|
|
||||||
{
|
|
||||||
// Not using any fancy permissions in android yet...
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PlatformHelperAndroid::machineHostname() const
|
QString PlatformHelperAndroid::machineHostname() const
|
||||||
{
|
{
|
||||||
// QSysInfo::machineHostname always gives "localhost" on android... best we can do here is:
|
// QSysInfo::machineHostname always gives "localhost" on android... best we can do here is:
|
||||||
@ -265,14 +254,6 @@ void PlatformHelperAndroid::shareFile(const QString &fileName)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformHelperAndroid::permissionRequestFinished(const QtAndroid::PermissionResultMap &result)
|
|
||||||
{
|
|
||||||
foreach (const QString &key, result.keys()) {
|
|
||||||
qDebug() << "Permission result:" << key << static_cast<int>(result.value(key));
|
|
||||||
}
|
|
||||||
emit m_instance->permissionsRequestFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformHelperAndroid::darkModeEnabledChangedJNI()
|
void PlatformHelperAndroid::darkModeEnabledChangedJNI()
|
||||||
{
|
{
|
||||||
if (m_instance) {
|
if (m_instance) {
|
||||||
|
|||||||
@ -45,11 +45,8 @@ public:
|
|||||||
|
|
||||||
explicit PlatformHelperAndroid(QObject *parent = nullptr);
|
explicit PlatformHelperAndroid(QObject *parent = nullptr);
|
||||||
|
|
||||||
Q_INVOKABLE void requestPermissions() override;
|
|
||||||
|
|
||||||
Q_INVOKABLE void hideSplashScreen() override;
|
Q_INVOKABLE void hideSplashScreen() override;
|
||||||
|
|
||||||
bool hasPermissions() const override;
|
|
||||||
QString machineHostname() const override;
|
QString machineHostname() const override;
|
||||||
QString deviceSerial() const override;
|
QString deviceSerial() const override;
|
||||||
QString device() const override;
|
QString device() const override;
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
#include "platformpermissionsandroid.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr;
|
||||||
|
|
||||||
|
QHash<PlatformPermissions::Permission, QStringList> permissionMap = {
|
||||||
|
// TODO: Once QtBluetooth does not request the COARSE_LOCATION for Bluetooth any more, remove it from here. The new Bluetooth permissions would be enough.
|
||||||
|
{PlatformPermissions::PermissionBluetooth, {"android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT", "android.permission.ACCESS_COARSE_LOCATION"}},
|
||||||
|
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
|
||||||
|
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}},
|
||||||
|
{PlatformPermissions::PermissionNotifications, {"android.permission.POST_NOTIFICATIONS"}},
|
||||||
|
};
|
||||||
|
|
||||||
|
PlatformPermissionsAndroid::PlatformPermissionsAndroid(QObject *parent)
|
||||||
|
: PlatformPermissions{parent}
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
// If the user switches to the settings app and changes permission settings there, we won't get notified
|
||||||
|
// in any way, so let's just refresh when we become active
|
||||||
|
connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
|
||||||
|
if (state == Qt::ApplicationActive) {
|
||||||
|
emit bluetoothPermissionChanged();
|
||||||
|
emit locationPermissionChanged();
|
||||||
|
emit backgroundLocationPermissionChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permission permission)
|
||||||
|
{
|
||||||
|
qWarning() << "****** android permission request" << permission;
|
||||||
|
QtAndroid::requestPermissions({permissionMap.value(permission)}, &permissionResultCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsAndroid::openPermissionSettings()
|
||||||
|
{
|
||||||
|
QtAndroid::androidActivity().callMethod<void>("openPermissionSettings", "()V");
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermission(Permission permission) const
|
||||||
|
{
|
||||||
|
PermissionStatus status = PermissionStatusGranted;
|
||||||
|
QStringList androidPermissions = permissionMap.value(permission);
|
||||||
|
foreach (const QString androidPermission, androidPermissions) {
|
||||||
|
if (QtAndroid::shouldShowRequestPermissionRationale(androidPermission)) {
|
||||||
|
return PermissionStatusDenied;
|
||||||
|
}
|
||||||
|
if (QtAndroid::checkPermission(androidPermission) == QtAndroid::PermissionResult::Denied) {
|
||||||
|
status = PermissionStatusNotDetermined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsAndroid::permissionResultCallback(const QtAndroid::PermissionResultMap &/*results*/)
|
||||||
|
{
|
||||||
|
emit s_instance->bluetoothPermissionChanged();
|
||||||
|
emit s_instance->locationPermissionChanged();
|
||||||
|
emit s_instance->backgroundLocationPermissionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef PLATFORMPERMISSIONSANDROID_H
|
||||||
|
#define PLATFORMPERMISSIONSANDROID_H
|
||||||
|
|
||||||
|
#include "../platformpermissions.h"
|
||||||
|
|
||||||
|
#include <QtAndroidExtras/QtAndroid>
|
||||||
|
|
||||||
|
class PlatformPermissionsAndroid : public PlatformPermissions
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PlatformPermissionsAndroid(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
PermissionStatus checkPermission(Permission permission) const override;
|
||||||
|
|
||||||
|
void requestPermission(Permission permission) override;
|
||||||
|
void openPermissionSettings() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static PlatformPermissionsAndroid *s_instance;
|
||||||
|
static void permissionResultCallback(const QtAndroid::PermissionResultMap &results);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLATFORMPERMISSIONSANDROID_H
|
||||||
@ -44,13 +44,6 @@ PlatformHelperIOS::PlatformHelperIOS(QObject *parent) : PlatformHelper(parent)
|
|||||||
QObject::connect(screen, &QScreen::orientationChanged, qApp, [this](Qt::ScreenOrientation) {
|
QObject::connect(screen, &QScreen::orientationChanged, qApp, [this](Qt::ScreenOrientation) {
|
||||||
setBottomPanelColor(bottomPanelColor());
|
setBottomPanelColor(bottomPanelColor());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformHelperIOS::requestPermissions()
|
|
||||||
{
|
|
||||||
emit permissionsRequestFinished();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformHelperIOS::hideSplashScreen()
|
void PlatformHelperIOS::hideSplashScreen()
|
||||||
@ -58,11 +51,6 @@ void PlatformHelperIOS::hideSplashScreen()
|
|||||||
// Nothing to be done
|
// Nothing to be done
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformHelperIOS::hasPermissions() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PlatformHelperIOS::machineHostname() const
|
QString PlatformHelperIOS::machineHostname() const
|
||||||
{
|
{
|
||||||
return QSysInfo::machineHostName();
|
return QSysInfo::machineHostName();
|
||||||
|
|||||||
@ -41,11 +41,8 @@ class PlatformHelperIOS : public PlatformHelper
|
|||||||
public:
|
public:
|
||||||
explicit PlatformHelperIOS(QObject *parent = nullptr);
|
explicit PlatformHelperIOS(QObject *parent = nullptr);
|
||||||
|
|
||||||
Q_INVOKABLE virtual void requestPermissions() override;
|
|
||||||
|
|
||||||
Q_INVOKABLE void hideSplashScreen() override;
|
Q_INVOKABLE void hideSplashScreen() override;
|
||||||
|
|
||||||
virtual bool hasPermissions() const override;
|
|
||||||
virtual QString machineHostname() const override;
|
virtual QString machineHostname() const override;
|
||||||
virtual QString device() const override;
|
virtual QString device() const override;
|
||||||
virtual QString deviceSerial() const override;
|
virtual QString deviceSerial() const override;
|
||||||
|
|||||||
69
nymea-app/platformintegration/ios/platformpermissionsios.cpp
Normal file
69
nymea-app/platformintegration/ios/platformpermissionsios.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "platformpermissionsios.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
PlatformPermissionsIOS *PlatformPermissionsIOS::s_instance = nullptr;
|
||||||
|
|
||||||
|
PlatformPermissionsIOS::PlatformPermissionsIOS(QObject *parent)
|
||||||
|
: PlatformPermissions{parent}
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
initObjC();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissionsIOS *PlatformPermissionsIOS::instance()
|
||||||
|
{
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsIOS::checkPermission(Permission permission) const
|
||||||
|
{
|
||||||
|
switch (permission) {
|
||||||
|
case PermissionLocalNetwork:
|
||||||
|
return checkLocalNetworkPermission();
|
||||||
|
case PermissionNotifications:
|
||||||
|
return m_notificationPermissions;
|
||||||
|
case PermissionBackgroundLocation:
|
||||||
|
return checkBackgroundLocationPermission();
|
||||||
|
case PermissionLocation:
|
||||||
|
return checkLocationPermission();
|
||||||
|
case PermissionBluetooth:
|
||||||
|
return checkBluetoothPermission();
|
||||||
|
default:
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestPermission(Permission permission)
|
||||||
|
{
|
||||||
|
switch (permission) {
|
||||||
|
case PermissionLocalNetwork:
|
||||||
|
requestLocalNetworkPermission();
|
||||||
|
break;
|
||||||
|
case PermissionNotifications:
|
||||||
|
requestNotificationPermission();
|
||||||
|
break;
|
||||||
|
case PermissionBackgroundLocation:
|
||||||
|
requestBackgroundLocationPermission();
|
||||||
|
break;
|
||||||
|
case PermissionLocation:
|
||||||
|
requestLocationPermission();
|
||||||
|
break;
|
||||||
|
case PermissionBluetooth:
|
||||||
|
requestBluetoothPermission();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsIOS::checkLocalNetworkPermission() const
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
return settings.value("askedForLocalNetworkPermission", false).toBool() ? PermissionStatusGranted : PermissionStatusNotDetermined;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestLocalNetworkPermission()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue("askedForLocalNetworkPermission", true);
|
||||||
|
emit localNetworkPermissionChanged();
|
||||||
|
}
|
||||||
51
nymea-app/platformintegration/ios/platformpermissionsios.h
Normal file
51
nymea-app/platformintegration/ios/platformpermissionsios.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef PLATFORMPERMISSIONSIOS_H
|
||||||
|
#define PLATFORMPERMISSIONSIOS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "../platformpermissions.h"
|
||||||
|
|
||||||
|
#if __OBJC__
|
||||||
|
@class CLLocationManager;
|
||||||
|
@class CBCentralManager;
|
||||||
|
#else
|
||||||
|
typedef void CLLocationManager;
|
||||||
|
typedef void CBCentralManager;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class PlatformPermissionsIOS : public PlatformPermissions
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PlatformPermissionsIOS(QObject *parent = nullptr);
|
||||||
|
static PlatformPermissionsIOS *instance();
|
||||||
|
|
||||||
|
PermissionStatus checkPermission(Permission permission) const override;
|
||||||
|
void requestPermission(Permission permission) override;
|
||||||
|
void openPermissionSettings() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initObjC();
|
||||||
|
void refreshNotificationsPermission();
|
||||||
|
|
||||||
|
static PlatformPermissionsIOS *s_instance;
|
||||||
|
|
||||||
|
PermissionStatus checkLocalNetworkPermission() const;
|
||||||
|
PermissionStatus checkBluetoothPermission() const;
|
||||||
|
PermissionStatus checkLocationPermission() const;
|
||||||
|
PermissionStatus checkBackgroundLocationPermission() const;
|
||||||
|
|
||||||
|
void requestLocalNetworkPermission();
|
||||||
|
void requestNotificationPermission();
|
||||||
|
void requestBluetoothPermission();
|
||||||
|
void requestLocationPermission();
|
||||||
|
void requestBackgroundLocationPermission();
|
||||||
|
|
||||||
|
PermissionStatus m_notificationPermissions = PermissionStatusNotDetermined;
|
||||||
|
|
||||||
|
|
||||||
|
CLLocationManager *m_locationManager = nullptr;
|
||||||
|
CBCentralManager *m_bluetoothManager = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLATFORMPERMISSIONSIOS_H
|
||||||
144
nymea-app/platformintegration/ios/platformpermissionsios.mm
Normal file
144
nymea-app/platformintegration/ios/platformpermissionsios.mm
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "platformpermissionsios.h"
|
||||||
|
|
||||||
|
#import <UserNotifications/UNUserNotificationCenter.h>
|
||||||
|
#import <UserNotifications/UNNotificationSettings.h>
|
||||||
|
#import <CoreLocation/CoreLocation.h>
|
||||||
|
#import <CoreBluetooth/CoreBluetooth.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface LocationManagerPermissionDelegate : NSObject <CLLocationManagerDelegate>
|
||||||
|
@end
|
||||||
|
@implementation LocationManagerPermissionDelegate
|
||||||
|
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
|
||||||
|
emit PlatformPermissionsIOS::instance()->locationPermissionChanged();
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface BluetoothManagerDelegate: NSObject<CBCentralManagerDelegate>
|
||||||
|
@end
|
||||||
|
@implementation BluetoothManagerDelegate
|
||||||
|
- (void)centralManagerDidUpdateState:(CBCentralManager *)manager {
|
||||||
|
emit PlatformPermissionsIOS::instance()->bluetoothPermissionChanged();
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::initObjC()
|
||||||
|
{
|
||||||
|
m_locationManager = [[CLLocationManager alloc] init];
|
||||||
|
m_locationManager.delegate = [[LocationManagerPermissionDelegate alloc] init];
|
||||||
|
|
||||||
|
// Refresh notification permissions right away as that can be retrieved async only. We wanna be ready when the app requests it.
|
||||||
|
refreshNotificationsPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::refreshNotificationsPermission()
|
||||||
|
{
|
||||||
|
// Notification permissions can be retrieved async only.
|
||||||
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
||||||
|
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) {
|
||||||
|
PermissionStatus newPermission;
|
||||||
|
switch (settings.authorizationStatus) {
|
||||||
|
case UNAuthorizationStatusNotDetermined:
|
||||||
|
newPermission = PermissionStatusNotDetermined;
|
||||||
|
break;
|
||||||
|
case UNAuthorizationStatusDenied:
|
||||||
|
newPermission = PermissionStatusDenied;
|
||||||
|
break;
|
||||||
|
case UNAuthorizationStatusAuthorized:
|
||||||
|
case UNAuthorizationStatusProvisional:
|
||||||
|
case UNAuthorizationStatusEphemeral:
|
||||||
|
newPermission = PermissionStatusGranted;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (newPermission != m_notificationPermissions) {
|
||||||
|
m_notificationPermissions = newPermission;
|
||||||
|
emit notificationsPermissionChanged();
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestNotificationPermission()
|
||||||
|
{
|
||||||
|
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
|
||||||
|
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionBadge + UNAuthorizationOptionSound)
|
||||||
|
completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
||||||
|
m_notificationPermissions = granted ? PermissionStatusGranted : PermissionStatusDenied;
|
||||||
|
emit notificationsPermissionChanged();
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsIOS::checkBluetoothPermission() const
|
||||||
|
{
|
||||||
|
// iOS 13.0 would have an api but it's more complicated and also deprecated... Ignoring...
|
||||||
|
if (@available(iOS 13.1, *)) {
|
||||||
|
switch (CBCentralManager.authorization) {
|
||||||
|
case CBManagerAuthorizationAllowedAlways:
|
||||||
|
case CBManagerAuthorizationRestricted:
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
case CBManagerAuthorizationDenied:
|
||||||
|
return PermissionStatusDenied;
|
||||||
|
case CBManagerAuthorizationNotDetermined:
|
||||||
|
return PermissionStatusNotDetermined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Before iOS 13, Bluetooth permissions are not required
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestBluetoothPermission()
|
||||||
|
{
|
||||||
|
// Instantiating a Bluetooth manager just trigger the popup...
|
||||||
|
if (!m_bluetoothManager) {
|
||||||
|
BluetoothManagerDelegate *delegate = [[BluetoothManagerDelegate alloc] init];
|
||||||
|
m_bluetoothManager = [[CBCentralManager alloc] initWithDelegate:delegate queue:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsIOS::checkLocationPermission() const
|
||||||
|
{
|
||||||
|
switch ([CLLocationManager authorizationStatus]) {
|
||||||
|
case kCLAuthorizationStatusNotDetermined:
|
||||||
|
return PermissionStatusNotDetermined;
|
||||||
|
case kCLAuthorizationStatusAuthorizedAlways:
|
||||||
|
case kCLAuthorizationStatusAuthorizedWhenInUse:
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
case kCLAuthorizationStatusDenied:
|
||||||
|
case kCLAuthorizationStatusRestricted:
|
||||||
|
return PermissionStatusDenied;
|
||||||
|
}
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestLocationPermission()
|
||||||
|
{
|
||||||
|
if ([m_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
|
||||||
|
[m_locationManager requestWhenInUseAuthorization];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissionsIOS::checkBackgroundLocationPermission() const
|
||||||
|
{
|
||||||
|
switch ([CLLocationManager authorizationStatus]) {
|
||||||
|
case kCLAuthorizationStatusNotDetermined:
|
||||||
|
return PermissionStatusNotDetermined;
|
||||||
|
case kCLAuthorizationStatusAuthorizedAlways:
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
case kCLAuthorizationStatusAuthorizedWhenInUse:
|
||||||
|
case kCLAuthorizationStatusDenied:
|
||||||
|
case kCLAuthorizationStatusRestricted:
|
||||||
|
return PermissionStatusDenied;
|
||||||
|
}
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::requestBackgroundLocationPermission()
|
||||||
|
{
|
||||||
|
if ([m_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
|
||||||
|
[m_locationManager requestAlwaysAuthorization];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformPermissionsIOS::openPermissionSettings()
|
||||||
|
{
|
||||||
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
||||||
|
}
|
||||||
@ -8,9 +8,18 @@
|
|||||||
|
|
||||||
#import "Firebase/Firebase.h"
|
#import "Firebase/Firebase.h"
|
||||||
|
|
||||||
|
@interface FirebaseDelegate: NSObject<FIRMessagingDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FirebaseDelegate
|
||||||
|
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
|
||||||
|
qDebug() << "Firebase token received:" << QString::fromNSString(fcmToken);
|
||||||
|
dynamic_cast<PushNotifications*>(PushNotifications::instance())->setFirebaseRegistrationToken(QString::fromNSString(fcmToken));
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
// This is hidden, so we declare it here to hook into it
|
// This is hidden, so we declare it here to hook into it
|
||||||
@interface QIOSApplicationDelegate: UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate,FIRMessagingDelegate>
|
@interface QIOSApplicationDelegate: UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
//add a category to QIOSApplicationDelegate
|
//add a category to QIOSApplicationDelegate
|
||||||
@ -23,50 +32,12 @@
|
|||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
|
||||||
// Use Firebase library to configure APIs
|
|
||||||
[FIRApp configure];
|
|
||||||
[FIRMessaging messaging].delegate = self;
|
|
||||||
|
|
||||||
|
|
||||||
// Register to receive notifications from the system
|
|
||||||
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
||||||
center.delegate = self;
|
center.delegate = self;
|
||||||
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
|
|
||||||
if(!error){
|
|
||||||
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
NSLog(@"registering for remote notifications");
|
|
||||||
qDebug() << "Registering for remote notifications";
|
|
||||||
|
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
||||||
NSLog(@"Did Register for Remote Notifications with Device Token (%@)", deviceToken);
|
|
||||||
|
|
||||||
const unsigned *tokenBytes = (const unsigned*)[deviceToken bytes];
|
|
||||||
NSString *tokenStr = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
|
|
||||||
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
|
|
||||||
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
|
|
||||||
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
|
|
||||||
|
|
||||||
// We've switched to firebase... Not emitting the native APNS token
|
|
||||||
|
|
||||||
// qDebug() << "Registering for remote notifications";
|
|
||||||
// qDebug() << "Token description:" << QString::fromNSString(deviceToken.description);
|
|
||||||
// qDebug() << "Parsed token:" << QString::fromNSString(tokenStr);
|
|
||||||
PushNotifications::instance()->setAPNSRegistrationToken(QString::fromNSString(tokenStr));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
||||||
NSLog(@"Did Fail to Register for Remote Notifications");
|
|
||||||
NSLog(@"%@, %@", error, error.localizedDescription);
|
|
||||||
qWarning() << "Failed to register for notifications:" << QString::fromNSString(error.localizedDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
|
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
|
||||||
NSLog(@"User Info : %@",notification.request.content.userInfo);
|
NSLog(@"User Info : %@",notification.request.content.userInfo);
|
||||||
qDebug() << "willPresentNotification called!";
|
qDebug() << "willPresentNotification called!";
|
||||||
@ -91,20 +62,15 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
|
|
||||||
NSLog(@"FCM registration token: %@", fcmToken);
|
|
||||||
// Notify about received token.
|
|
||||||
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:
|
|
||||||
@"FCMToken" object:nil userInfo:dataDict];
|
|
||||||
// Note: This callback is fired at each app startup and whenever a new token is generated.
|
|
||||||
//qDebug() << "Firebase token received:" << QString::fromNSString(fcmToken);
|
|
||||||
PushNotifications::instance()->setFirebaseRegistrationToken(QString::fromNSString(fcmToken));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo {
|
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo {
|
||||||
qDebug() << "didReceiveRemoteNotification called";
|
qDebug() << "didReceiveRemoteNotification called";
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
void PushNotifications::registerObjC()
|
||||||
|
{
|
||||||
|
[FIRApp configure];
|
||||||
|
[FIRMessaging messaging].delegate = [[FirebaseDelegate alloc] init];
|
||||||
|
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
||||||
|
}
|
||||||
|
|||||||
64
nymea-app/platformintegration/platformpermissions.cpp
Normal file
64
nymea-app/platformintegration/platformpermissions.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "platformpermissions.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
#include "android/platformpermissionsandroid.h"
|
||||||
|
#elif defined Q_OS_IOS
|
||||||
|
#include "ios/platformpermissionsios.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PlatformPermissions *PlatformPermissions::instance()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
return new PlatformPermissionsAndroid();
|
||||||
|
#elif defined Q_OS_IOS
|
||||||
|
return new PlatformPermissionsIOS();
|
||||||
|
#else
|
||||||
|
return new PlatformPermissions();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlatformPermissions::PlatformPermissions(QObject *parent)
|
||||||
|
: QObject{parent}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject *PlatformPermissions::qmlProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||||
|
{
|
||||||
|
Q_UNUSED(engine)
|
||||||
|
Q_UNUSED(scriptEngine)
|
||||||
|
return instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::localNetworkPermission() const
|
||||||
|
{
|
||||||
|
return checkPermission(PermissionLocalNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::bluetoothPermission() const
|
||||||
|
{
|
||||||
|
return checkPermission(PermissionBluetooth);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::locationPermission() const
|
||||||
|
{
|
||||||
|
return checkPermission(PermissionLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::backgroundLocationPermission() const
|
||||||
|
{
|
||||||
|
return checkPermission(PermissionBackgroundLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::notificationsPermission() const
|
||||||
|
{
|
||||||
|
return checkPermission(PermissionNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformPermissions::PermissionStatus PlatformPermissions::checkPermission(Permission permission) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(permission)
|
||||||
|
return PermissionStatusGranted;
|
||||||
|
}
|
||||||
|
|
||||||
65
nymea-app/platformintegration/platformpermissions.h
Normal file
65
nymea-app/platformintegration/platformpermissions.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef PLATFORMPERMISSIONS_H
|
||||||
|
#define PLATFORMPERMISSIONS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QQmlEngine;
|
||||||
|
class QJSEngine;
|
||||||
|
|
||||||
|
class PlatformPermissions : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(PermissionStatus localNetworkPermission READ localNetworkPermission NOTIFY localNetworkPermissionChanged)
|
||||||
|
Q_PROPERTY(PermissionStatus bluetoothPermission READ bluetoothPermission NOTIFY bluetoothPermissionChanged)
|
||||||
|
Q_PROPERTY(PermissionStatus locationPermission READ locationPermission NOTIFY locationPermissionChanged)
|
||||||
|
Q_PROPERTY(PermissionStatus backgroundLocationPermission READ backgroundLocationPermission NOTIFY backgroundLocationPermissionChanged)
|
||||||
|
Q_PROPERTY(PermissionStatus notificationsPermission READ notificationsPermission NOTIFY notificationsPermissionChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Permission {
|
||||||
|
PermissionNone = 0x00,
|
||||||
|
PermissionLocalNetwork = 0x01,
|
||||||
|
PermissionBluetooth = 0x02,
|
||||||
|
PermissionLocation = 0x04,
|
||||||
|
PermissionBackgroundLocation = 0x08,
|
||||||
|
PermissionNotifications = 0x10
|
||||||
|
};
|
||||||
|
Q_ENUM(Permission)
|
||||||
|
Q_DECLARE_FLAGS(Permissions, Permission)
|
||||||
|
Q_FLAG(Permissions)
|
||||||
|
|
||||||
|
enum PermissionStatus {
|
||||||
|
PermissionStatusNotDetermined,
|
||||||
|
PermissionStatusGranted,
|
||||||
|
PermissionStatusDenied,
|
||||||
|
};
|
||||||
|
Q_ENUM(PermissionStatus)
|
||||||
|
|
||||||
|
static PlatformPermissions* instance();
|
||||||
|
static QObject *qmlProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||||
|
virtual ~PlatformPermissions() = default;
|
||||||
|
|
||||||
|
PermissionStatus localNetworkPermission() const;
|
||||||
|
PermissionStatus bluetoothPermission() const;
|
||||||
|
PermissionStatus locationPermission() const;
|
||||||
|
PermissionStatus backgroundLocationPermission() const;
|
||||||
|
PermissionStatus notificationsPermission() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual PermissionStatus checkPermission(Permission permission) const;
|
||||||
|
Q_INVOKABLE virtual void requestPermission(Permission permission) { Q_UNUSED(permission) }
|
||||||
|
Q_INVOKABLE virtual void openPermissionSettings() {}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void localNetworkPermissionChanged();
|
||||||
|
void bluetoothPermissionChanged();
|
||||||
|
void locationPermissionChanged();
|
||||||
|
void backgroundLocationPermissionChanged();
|
||||||
|
void notificationsPermissionChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit PlatformPermissions(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLATFORMPERMISSIONS_H
|
||||||
@ -42,33 +42,7 @@ static PushNotifications *m_client_pointer;
|
|||||||
|
|
||||||
PushNotifications::PushNotifications(QObject *parent) : QObject(parent)
|
PushNotifications::PushNotifications(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
#if defined Q_OS_ANDROID && defined WITH_FIREBASE
|
|
||||||
qDebug() << "Checking for play services";
|
|
||||||
jboolean playServicesAvailable = QAndroidJniObject::callStaticMethod<jboolean>("io.guh.nymeaapp.NymeaAppNotificationService", "checkPlayServices", "()Z");
|
|
||||||
if (playServicesAvailable) {
|
|
||||||
qDebug() << "Setting up firebase";
|
|
||||||
m_client_pointer = this;
|
|
||||||
m_firebaseApp = ::firebase::App::Create(::firebase::AppOptions(), QAndroidJniEnvironment(), QtAndroid::androidActivity().object());
|
|
||||||
m_firebase_initializer.Initialize(m_firebaseApp, nullptr, [](::firebase::App * fapp, void *) {
|
|
||||||
return ::firebase::messaging::Initialize( *fapp, (::firebase::messaging::Listener *)m_client_pointer);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
qDebug() << "Google Play Services not available. Cannot connect to push client.";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef UBPORTS
|
|
||||||
m_pushClient = new PushClient(this);
|
|
||||||
m_pushClient->setAppId("io.guh.nymeaapp_nymea-app");
|
|
||||||
connect(m_pushClient, &PushClient::tokenChanged, this, [this](const QString &token) {
|
|
||||||
// On UBPorts, core and cloud use the same token
|
|
||||||
m_coreToken = token;
|
|
||||||
emit coreTokenChanged();
|
|
||||||
m_cloudToken = m_coreToken;
|
|
||||||
emit cloudTokenChanged();
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PushNotifications::~PushNotifications()
|
PushNotifications::~PushNotifications()
|
||||||
@ -91,6 +65,57 @@ PushNotifications *PushNotifications::instance()
|
|||||||
return pushNotifications;
|
return pushNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PushNotifications::enabled() const
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushNotifications::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (m_enabled == enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enabled = enabled;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
registerForPush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushNotifications::registerForPush()
|
||||||
|
{
|
||||||
|
#if defined Q_OS_ANDROID && defined WITH_FIREBASE
|
||||||
|
qDebug() << "Checking for play services";
|
||||||
|
jboolean playServicesAvailable = QAndroidJniObject::callStaticMethod<jboolean>("io.guh.nymeaapp.NymeaAppNotificationService", "checkPlayServices", "()Z");
|
||||||
|
if (playServicesAvailable) {
|
||||||
|
qDebug() << "Setting up firebase";
|
||||||
|
m_client_pointer = this;
|
||||||
|
m_firebaseApp = ::firebase::App::Create(::firebase::AppOptions(), QAndroidJniEnvironment(), QtAndroid::androidActivity().object());
|
||||||
|
m_firebase_initializer.Initialize(m_firebaseApp, nullptr, [](::firebase::App * fapp, void *) {
|
||||||
|
return ::firebase::messaging::Initialize( *fapp, (::firebase::messaging::Listener *)m_client_pointer);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
qDebug() << "Google Play Services not available. Cannot connect to push client.";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UBPORTS
|
||||||
|
m_pushClient = new PushClient(this);
|
||||||
|
m_pushClient->setAppId("io.guh.nymeaapp_nymea-app");
|
||||||
|
connect(m_pushClient, &PushClient::tokenChanged, this, [this](const QString &token) {
|
||||||
|
m_token = token;
|
||||||
|
emit tokenChanged();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
registerObjC();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
QString PushNotifications::service() const
|
QString PushNotifications::service() const
|
||||||
{
|
{
|
||||||
#if defined Q_OS_ANDROID
|
#if defined Q_OS_ANDROID
|
||||||
@ -108,28 +133,16 @@ QString PushNotifications::clientId() const
|
|||||||
return PlatformHelper::instance()->deviceSerial();
|
return PlatformHelper::instance()->deviceSerial();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PushNotifications::coreToken() const
|
QString PushNotifications::token() const
|
||||||
{
|
{
|
||||||
return m_coreToken;
|
return m_token;
|
||||||
}
|
|
||||||
|
|
||||||
QString PushNotifications::cloudToken() const
|
|
||||||
{
|
|
||||||
return m_cloudToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushNotifications::setAPNSRegistrationToken(const QString &apnsRegistrationToken)
|
|
||||||
{
|
|
||||||
qDebug() << "Received APNS push notification token:" << apnsRegistrationToken;
|
|
||||||
m_cloudToken = apnsRegistrationToken;
|
|
||||||
emit cloudTokenChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushNotifications::setFirebaseRegistrationToken(const QString &firebaseRegistrationToken)
|
void PushNotifications::setFirebaseRegistrationToken(const QString &firebaseRegistrationToken)
|
||||||
{
|
{
|
||||||
qDebug() << "Received Firebase/APNS push notification token:" << firebaseRegistrationToken;
|
qDebug() << "Received Firebase/APNS push notification token:" << firebaseRegistrationToken;
|
||||||
m_coreToken = firebaseRegistrationToken;
|
m_token = firebaseRegistrationToken;
|
||||||
emit coreTokenChanged();
|
emit tokenChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined Q_OS_ANDROID && defined WITH_FIREBASE
|
#if defined Q_OS_ANDROID && defined WITH_FIREBASE
|
||||||
@ -140,11 +153,8 @@ void PushNotifications::OnMessage(const firebase::messaging::Message &message)
|
|||||||
|
|
||||||
void PushNotifications::OnTokenReceived(const char *token)
|
void PushNotifications::OnTokenReceived(const char *token)
|
||||||
{
|
{
|
||||||
qDebug() << "Firebase token received:" << token;
|
m_token = QString(token);
|
||||||
// On Android, both, core and cloud use the same token
|
qDebug() << "Firebase token received:" << m_token;
|
||||||
m_coreToken = QString(token);
|
emit tokenChanged();
|
||||||
emit coreTokenChanged();
|
|
||||||
m_cloudToken = m_coreToken;
|
|
||||||
emit cloudTokenChanged();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -51,10 +51,10 @@ class PushNotifications : public QObject
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||||
Q_PROPERTY(QString service READ service CONSTANT)
|
Q_PROPERTY(QString service READ service CONSTANT)
|
||||||
Q_PROPERTY(QString clientId READ clientId CONSTANT)
|
Q_PROPERTY(QString clientId READ clientId CONSTANT)
|
||||||
Q_PROPERTY(QString cloudToken READ cloudToken NOTIFY cloudTokenChanged)
|
Q_PROPERTY(QString token READ token NOTIFY tokenChanged)
|
||||||
Q_PROPERTY(QString coreToken READ coreToken NOTIFY coreTokenChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PushNotifications(QObject *parent = nullptr);
|
explicit PushNotifications(QObject *parent = nullptr);
|
||||||
@ -63,18 +63,19 @@ public:
|
|||||||
static QObject* pushNotificationsProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
static QObject* pushNotificationsProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||||
static PushNotifications* instance();
|
static PushNotifications* instance();
|
||||||
|
|
||||||
|
bool enabled() const;
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
QString service() const;
|
QString service() const;
|
||||||
QString clientId() const;
|
QString clientId() const;
|
||||||
QString coreToken() const;
|
QString token() const;
|
||||||
QString cloudToken() const;
|
|
||||||
|
|
||||||
// Called by Objective-C++ on iOS
|
// Called by Objective-C++ on iOS
|
||||||
void setAPNSRegistrationToken(const QString &apnsRegistrationToken);
|
|
||||||
void setFirebaseRegistrationToken(const QString &firebaseRegistrationToken);
|
void setFirebaseRegistrationToken(const QString &firebaseRegistrationToken);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void coreTokenChanged();
|
void enabledChanged();
|
||||||
void cloudTokenChanged();
|
void tokenChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -92,10 +93,16 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For nymea:core plugin based push notifications
|
|
||||||
QString m_coreToken;
|
void registerForPush();
|
||||||
// for nymea:cloud based push notifications (deprecated)
|
|
||||||
QString m_cloudToken;
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
void registerObjC();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool m_enabled = false;
|
||||||
|
QString m_token;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PUSHNOTIFICATIONS_H
|
#endif // PUSHNOTIFICATIONS_H
|
||||||
|
|||||||
@ -106,6 +106,12 @@ ApplicationWindow {
|
|||||||
value: "cloudEnvironment" in app ? app.cloudEnvironment : settings.cloudEnvironment
|
value: "cloudEnvironment" in app ? app.cloudEnvironment : settings.cloudEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: PushNotifications
|
||||||
|
property: "enabled"
|
||||||
|
value: PlatformPermissions.notificationsPermission === PlatformPermissions.PermissionStatusGranted
|
||||||
|
}
|
||||||
|
|
||||||
ConfiguredHostsModel {
|
ConfiguredHostsModel {
|
||||||
id: configuredHostsModel
|
id: configuredHostsModel
|
||||||
}
|
}
|
||||||
@ -136,7 +142,9 @@ ApplicationWindow {
|
|||||||
property NymeaDiscovery nymeaDiscovery: NymeaDiscovery {
|
property NymeaDiscovery nymeaDiscovery: NymeaDiscovery {
|
||||||
objectName: "discovery"
|
objectName: "discovery"
|
||||||
awsClient: AWSClient
|
awsClient: AWSClient
|
||||||
|
bluetoothDiscoveryEnabled: PlatformPermissions.bluetoothPermission === PlatformPermissions.PermissionStatusGranted
|
||||||
// discovering: pageStack.currentItem.objectName === "discoveryPage"
|
// discovering: pageStack.currentItem.objectName === "discoveryPage"
|
||||||
|
Component.onCompleted: console.warn("****************** local net perm", PlatformPermissions.localNetworkPermission, discovering, PlatformPermissions.localNetworkPermission === PlatformPermissions.PermissionStatusGranted, PlatformPermissions.PermissionStatusGranted)
|
||||||
}
|
}
|
||||||
|
|
||||||
property var supportedInterfaces: [
|
property var supportedInterfaces: [
|
||||||
|
|||||||
@ -126,6 +126,12 @@ Item {
|
|||||||
target: nymeaDiscovery
|
target: nymeaDiscovery
|
||||||
property: "discovering"
|
property: "discovering"
|
||||||
value: engine.jsonRpcClient.currentHost === null
|
value: engine.jsonRpcClient.currentHost === null
|
||||||
|
&& (PlatformPermissions.localNetworkPermission === PlatformPermissions.PermissionStatusGranted
|
||||||
|
// This OR wouldn't be needed but we introduced the permission handling later and the localNetworkPerm can't be read on iOS.
|
||||||
|
// If there are configured hosts, it means that we actally already have the permission even though PlatformPermissions thinks we wouldn't...
|
||||||
|
// So skipping the check in that case for now (1.6)
|
||||||
|
|| configuredHostsModel.count > 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property alias pageStack: _pageStack
|
readonly property alias pageStack: _pageStack
|
||||||
@ -137,7 +143,6 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
setupPushNotifications();
|
|
||||||
if (configuredHost.uuid.toString() !== "{00000000-0000-0000-0000-000000000000}") {
|
if (configuredHost.uuid.toString() !== "{00000000-0000-0000-0000-000000000000}") {
|
||||||
print("Configured host id is", configuredHost.uuid)
|
print("Configured host id is", configuredHost.uuid)
|
||||||
var cachedHost = nymeaDiscovery.nymeaHosts.find(configuredHost.uuid);
|
var cachedHost = nymeaDiscovery.nymeaHosts.find(configuredHost.uuid);
|
||||||
@ -149,6 +154,7 @@ Item {
|
|||||||
} else if (autoConnectHost.length > 0 && index === 0) {
|
} else if (autoConnectHost.length > 0 && index === 0) {
|
||||||
var host = nymeaDiscovery.nymeaHosts.createLanHost(Configuration.systemName, autoConnectHost);
|
var host = nymeaDiscovery.nymeaHosts.createLanHost(Configuration.systemName, autoConnectHost);
|
||||||
engine.jsonRpcClient.connectToHost(host)
|
engine.jsonRpcClient.connectToHost(host)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Only hide the splash right away if we're not trying to connect to something
|
// Only hide the splash right away if we're not trying to connect to something
|
||||||
@ -223,43 +229,13 @@ Item {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old nymea:cloud based push notifications...
|
|
||||||
function setupPushNotifications(askForPermissions) {
|
|
||||||
if (askForPermissions === undefined) {
|
|
||||||
askForPermissions = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AWSClient.isLoggedIn) {
|
|
||||||
print("AWS not logged in. Cannot register for push");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PushNotifications.cloudToken.length === 0) {
|
|
||||||
print("Don't have a token yet. Cannot register for push");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PlatformHelper.hasPermissions) {
|
|
||||||
if (askForPermissions) {
|
|
||||||
PlatformHelper.requestPermissions();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AWSClient.registerPushNotificationEndpoint(
|
|
||||||
PushNotifications.cloudToken,
|
|
||||||
PlatformHelper.machineHostname,
|
|
||||||
PushNotifications.clientId,
|
|
||||||
PlatformHelper.deviceManufacturer,
|
|
||||||
PlatformHelper.deviceModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New, nymea thing based push notifactions
|
// New, nymea thing based push notifactions
|
||||||
function updatePushNotificationThings() {
|
function updatePushNotificationThings() {
|
||||||
if (PushNotifications.service == "") {
|
if (PushNotifications.service == "") {
|
||||||
print("This platform does not support push notifications")
|
print("This platform does not support push notifications")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!PushNotifications.coreToken) {
|
if (!PushNotifications.token) {
|
||||||
print("No push notification token available at this time. Not updating...");
|
print("No push notification token available at this time. Not updating...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -268,7 +244,7 @@ Item {
|
|||||||
print("Updating push notifications")
|
print("Updating push notifications")
|
||||||
print("Own push service:", PushNotifications.service);
|
print("Own push service:", PushNotifications.service);
|
||||||
print("Own client ID:", clientId);
|
print("Own client ID:", clientId);
|
||||||
print("Current token:", PushNotifications.coreToken);
|
print("Current token:", PushNotifications.token);
|
||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < engine.thingManager.things.count; i++) {
|
for (var i = 0; i < engine.thingManager.things.count; i++) {
|
||||||
@ -279,11 +255,15 @@ Item {
|
|||||||
var tokenParam = thing.paramByName("token")
|
var tokenParam = thing.paramByName("token")
|
||||||
print("Found a push notification thing for client id:", clientIdParam.value)
|
print("Found a push notification thing for client id:", clientIdParam.value)
|
||||||
if (clientIdParam.value === clientId) {
|
if (clientIdParam.value === clientId) {
|
||||||
if (tokenParam.value !== PushNotifications.coreToken) {
|
if (PlatformPermissions.notificationsPermission !== PlatformPermissions.PermissionStatusGranted) {
|
||||||
|
PlatformPermissions.requestPermission(PlatformPermissions.PermissionNotifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenParam.value !== PushNotifications.token) {
|
||||||
var params = [
|
var params = [
|
||||||
{ "paramTypeId": serviceParam.paramTypeId, "value": PushNotifications.service },
|
{ "paramTypeId": serviceParam.paramTypeId, "value": PushNotifications.service },
|
||||||
{ "paramTypeId": clientIdParam.paramTypeId, "value": clientId },
|
{ "paramTypeId": clientIdParam.paramTypeId, "value": clientId },
|
||||||
{ "paramTypeId": tokenParam.paramTypeId, "value": PushNotifications.coreToken }
|
{ "paramTypeId": tokenParam.paramTypeId, "value": PushNotifications.token }
|
||||||
];
|
];
|
||||||
print("Reconfiguring PushNotifications for", thing.name)
|
print("Reconfiguring PushNotifications for", thing.name)
|
||||||
engine.thingManager.reconfigureThing(thing.id, params);
|
engine.thingManager.reconfigureThing(thing.id, params);
|
||||||
@ -401,27 +381,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: PlatformHelper
|
|
||||||
onHasPermissionsChanged: {
|
|
||||||
setupPushNotifications(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: PushNotifications
|
|
||||||
onCloudTokenChanged: {
|
|
||||||
setupPushNotifications();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: AWSClient
|
|
||||||
onIsLoggedInChanged: {
|
|
||||||
setupPushNotifications()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: engine.thingManager
|
target: engine.thingManager
|
||||||
onFetchingDataChanged: {
|
onFetchingDataChanged: {
|
||||||
|
|||||||
@ -12,7 +12,10 @@ WizardPageBase {
|
|||||||
showExtraButton: true
|
showExtraButton: true
|
||||||
extraButtonText: qsTr("Demo mode")
|
extraButtonText: qsTr("Demo mode")
|
||||||
|
|
||||||
onNext: pageStack.push(connectionSelectionComponent)
|
onNext: {
|
||||||
|
PlatformPermissions.requestPermission(PlatformPermissions.PermissionLocalNetwork)
|
||||||
|
pageStack.push(connectionSelectionComponent)
|
||||||
|
}
|
||||||
onExtraButtonPressed: {
|
onExtraButtonPressed: {
|
||||||
var host = nymeaDiscovery.nymeaHosts.createWanHost("Demo server", "nymea://nymea.nymea.io:2222")
|
var host = nymeaDiscovery.nymeaHosts.createWanHost("Demo server", "nymea://nymea.nymea.io:2222")
|
||||||
engine.jsonRpcClient.connectToHost(host)
|
engine.jsonRpcClient.connectToHost(host)
|
||||||
@ -120,7 +123,13 @@ WizardPageBase {
|
|||||||
BigTile {
|
BigTile {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
onClicked: pageStack.push(wirelessInstructionsComponent)
|
onClicked: {
|
||||||
|
if (PlatformPermissions.bluetoothPermission != PlatformPermissions.PermissionStatusGranted) {
|
||||||
|
PlatformPermissions.requestPermission(PlatformPermissions.PermissionBluetooth)
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
pageStack.push(wirelessInstructionsComponent)
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
spacing: Style.margins
|
spacing: Style.margins
|
||||||
|
|||||||
@ -46,6 +46,18 @@ Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startWizard(thingClass) {
|
||||||
|
var page = pageStack.push(Qt.resolvedUrl("SetupWizard.qml"), {thingClass: thingClass});
|
||||||
|
page.done.connect(function() {
|
||||||
|
pageStack.pop(root, StackView.Immediate);
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
|
page.aborted.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Pane {
|
||||||
id: filterPane
|
id: filterPane
|
||||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||||
@ -167,14 +179,7 @@ Page {
|
|||||||
property ThingClass thingClass: thingClassesProxy.get(index)
|
property ThingClass thingClass: thingClassesProxy.get(index)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var page = pageStack.push(Qt.resolvedUrl("SetupWizard.qml"), {thingClass: thingClassesProxy.get(index)});
|
root.startWizard(thingClass)
|
||||||
page.done.connect(function() {
|
|
||||||
pageStack.pop(root, StackView.Immediate);
|
|
||||||
pageStack.pop();
|
|
||||||
})
|
|
||||||
page.aborted.connect(function() {
|
|
||||||
pageStack.pop();
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -375,6 +375,16 @@ Page {
|
|||||||
visible: paramRepeater.count > 0
|
visible: paramRepeater.count > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (root.thingClass.id.toString().match(/\{?f0dd4c03-0aca-42cc-8f34-9902457b05de\}?/)) {
|
||||||
|
console.warn("checking Notification permission!")
|
||||||
|
if (PlatformPermissions.notificationsPermission != PlatformPermissions.PermissionStatusGranted) {
|
||||||
|
console.warn("Notification permission missing!")
|
||||||
|
PlatformPermissions.requestPermission(PlatformPermissions.PermissionNotifications)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: paramRepeater
|
id: paramRepeater
|
||||||
model: engine.jsonRpcClient.ensureServerVersion("1.12") || d.thingDescriptor == null ? root.thingClass.paramTypes : null
|
model: engine.jsonRpcClient.ensureServerVersion("1.12") || d.thingDescriptor == null ? root.thingClass.paramTypes : null
|
||||||
@ -396,7 +406,7 @@ Page {
|
|||||||
return PushNotifications.service;
|
return PushNotifications.service;
|
||||||
}
|
}
|
||||||
if (paramType.id.toString().match(/\{?12ec06b2-44e7-486a-9169-31c684b91c8f\}?/)) {
|
if (paramType.id.toString().match(/\{?12ec06b2-44e7-486a-9169-31c684b91c8f\}?/)) {
|
||||||
return PushNotifications.coreToken;
|
return PushNotifications.token;
|
||||||
}
|
}
|
||||||
if (paramType.id.toString().match(/\{?d76da367-64e3-4b7d-aa84-c96b3acfb65e\}?/)) {
|
if (paramType.id.toString().match(/\{?d76da367-64e3-4b7d-aa84-c96b3acfb65e\}?/)) {
|
||||||
return PushNotifications.clientId + "+" + Configuration.appId;
|
return PushNotifications.clientId + "+" + Configuration.appId;
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<manifest package="io.guh.nymeaapp" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
|
<manifest package="io.guh.nymeaapp" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="nymea:app" android:icon="@mipmap/icon" android:roundIcon="@mipmap/round_icon" android:extractNativeLibs="true">
|
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="nymea:app" android:icon="@mipmap/icon" android:roundIcon="@mipmap/round_icon" android:extractNativeLibs="true">
|
||||||
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="io.guh.nymeaapp.NymeaAppActivity" android:label="nymea:app" android:screenOrientation="unspecified" android:launchMode="singleTop" android:theme="@style/SplashScreenTheme">
|
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="io.guh.nymeaapp.NymeaAppActivity" android:label="nymea:app" android:screenOrientation="unspecified" android:launchMode="singleTop" android:theme="@style/SplashScreenTheme" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
@ -63,7 +69,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
<activity android:process=":qt_controlsActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="io.guh.nymeaapp.NymeaAppControlsActivity" android:label="nymea:app" android:screenOrientation="unspecified" android:launchMode="standard">
|
<activity android:process=":qt_controlsActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="io.guh.nymeaapp.NymeaAppControlsActivity" android:label="nymea:app" android:screenOrientation="unspecified" android:launchMode="standard" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
@ -99,7 +105,7 @@
|
|||||||
|
|
||||||
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
|
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
|
||||||
|
|
||||||
<service android:process=":qt_service" android:name="io.guh.nymeaapp.NymeaAppService">
|
<service android:process=":qt_service" android:name="io.guh.nymeaapp.NymeaAppService" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
@ -130,7 +136,7 @@
|
|||||||
<service android:name="com.google.firebase.messaging.MessageForwardingService" android:exported="false">
|
<service android:name="com.google.firebase.messaging.MessageForwardingService" android:exported="false">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service android:name="io.guh.nymeaapp.NymeaAppNotificationService">
|
<service android:name="io.guh.nymeaapp.NymeaAppNotificationService" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
@ -163,6 +169,4 @@
|
|||||||
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
|
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
|
||||||
Remove the comment if you do not require these default features. -->
|
Remove the comment if you do not require these default features. -->
|
||||||
<!-- %%INSERT_FEATURES -->
|
<!-- %%INSERT_FEATURES -->
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
Reference in New Issue
Block a user