diff --git a/experiences/airconditioning/airconditioning.pro b/experiences/airconditioning/airconditioning.pro index fed671d9..67657a29 100644 --- a/experiences/airconditioning/airconditioning.pro +++ b/experiences/airconditioning/airconditioning.pro @@ -11,7 +11,7 @@ LIBS += -L$${top_builddir}/libnymea-app/ -lnymea-app android: { LIBS += -L$${top_builddir}/libnymea-app/$${ANDROID_TARGET_ARCH} - PRE_TARGETDEPS += $$top_builddir/libnymea-app/$${ANDROID_TARGET_ARCH}/libnymea-app.a + PRE_TARGETDEPS += $$top_builddir/libnymea-app/$${ANDROID_TARGET_ARCH}/libnymea-app_$${ANDROID_TARGET_ARCH}.a } INCLUDEPATH += $${top_srcdir}/libnymea-app/ diff --git a/nymea-app/nymea-app.pro b/nymea-app/nymea-app.pro index d8cef595..f7bb229b 100644 --- a/nymea-app/nymea-app.pro +++ b/nymea-app/nymea-app.pro @@ -12,11 +12,11 @@ qtHaveModule(webview) { DEFINES += HAVE_WEBVIEW } + INCLUDEPATH += $$top_srcdir/libnymea-app \ $$top_srcdir/experiences/airconditioning -LIBS += -L$$top_builddir/libnymea-app/ -lnymea-app \ - -L$$top_builddir/experiences/airconditioning -lnymea-app-airconditioning +linux:!android: LIBS += -L$$top_builddir/libnymea-app/ -lnymea-app -L$$top_builddir/experiences/airconditioning -lnymea-app-airconditioning win32:Debug:LIBS += -L$$top_builddir/libnymea-app/debug \ -L$$top_builddir/experiences/airconditioning/debug @@ -98,12 +98,11 @@ android { SOURCES += platformintegration/android/platformhelperandroid.cpp \ platformintegration/android/platformpermissionsandroid.cpp \ - # https://bugreports.qt.io/browse/QTBUG-83165 CORE_LIBS += -L$${top_builddir}/libnymea-app/$${ANDROID_TARGET_ARCH} AIRCONDITIONING_LIBS += -L$${top_builddir}/experiences/airconditioning/$${ANDROID_TARGET_ARCH} - LIBS += $${CORE_LIBS} $${AIRCONDITIONING_LIBS} - message("CORE_LIBS: $${CORE_LIBS}") + LIBS += $${CORE_LIBS} -lnymea-app_$${ANDROID_TARGET_ARCH} \ + $${AIRCONDITIONING_LIBS} -lnymea-app-airconditioning_$${ANDROID_TARGET_ARCH} versioninfo.files = ../version.txt versioninfo.path = / diff --git a/nymea-app/platformhelper.cpp b/nymea-app/platformhelper.cpp index 64d837aa..11c4bc17 100644 --- a/nymea-app/platformhelper.cpp +++ b/nymea-app/platformhelper.cpp @@ -38,7 +38,6 @@ #include #if defined Q_OS_ANDROID -#include #include "platformintegration/android/platformhelperandroid.h" #elif defined Q_OS_IOS #include "platformintegration/ios/platformhelperios.h" diff --git a/nymea-app/platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java b/nymea-app/platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java index 87b31da6..2eff4987 100644 --- a/nymea-app/platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java +++ b/nymea-app/platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java @@ -21,7 +21,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import android.view.WindowInsets; -public class NymeaAppActivity extends org.qtproject.qt5.android.bindings.QtActivity +public class NymeaAppActivity extends QtActivity { private static final String TAG = "nymea-app: NymeaAppActivity"; private static Context context = null; diff --git a/nymea-app/platformintegration/android/platformpermissionsandroid.cpp b/nymea-app/platformintegration/android/platformpermissionsandroid.cpp index 078724d7..bb144d8e 100644 --- a/nymea-app/platformintegration/android/platformpermissionsandroid.cpp +++ b/nymea-app/platformintegration/android/platformpermissionsandroid.cpp @@ -1,40 +1,156 @@ -// #include "platformpermissionsandroid.h" +#include "platformpermissionsandroid.h" -// #include -// #include -// #include +#include +#include +#include +#include -// #include "logging.h" -// NYMEA_LOGGING_CATEGORY(dcPlatformPermissions, "PlatformPermissions") +#include "logging.h" +NYMEA_LOGGING_CATEGORY(dcPlatformPermissions, "PlatformPermissions") -// PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr; +PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr; -// #define FLAG_ACTIVITY_NEW_TASK 0x10000000 +#define FLAG_ACTIVITY_NEW_TASK 0x10000000 -// 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(); -// emit notificationsPermissionChanged(); -// } -// }); +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(); + emit notificationsPermissionChanged(); + } + }); -// } +} -// void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permission permission) -// { -// if (permissionMap().contains(permission)) { -// qCDebug(dcPlatformPermissions()) << "Requesting permissions:" << permissionMap().value(permission); -// QtAndroid::requestPermissions({permissionMap().value(permission)}, &permissionResultCallback); -// } -// } +PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermission(Permission platformPermission) const +{ + PermissionStatus status = PermissionStatusGranted; + qCDebug(dcPlatformPermissions()) << "Checking permission" << platformPermission; + + switch (platformPermission) { + case PlatformPermissions::PermissionBluetooth: { + QBluetoothPermission permission; + + // Status prüfen + auto status = qApp->checkPermission(permission); + + switch (status) { + case Qt::PermissionStatus::Granted: + qCDebug(dcPlatformPermissions()) << "Bluetooth permission already granted."; + break; + case Qt::PermissionStatus::Denied: + qCDebug(dcPlatformPermissions()) << "Bluetooth permission denied."; + break; + case Qt::PermissionStatus::Undetermined: + qCDebug(dcPlatformPermissions()) << "Bluetooth permission not yet requested. Requesting..."; + qApp->requestPermission(permission, [](const QPermission &perm){ + if (perm.status() == Qt::PermissionStatus::Granted) + qCDebug(dcPlatformPermissions()) << "Bluetooth permission granted after request."; + else + qCDebug(dcPlatformPermissions()) << "Bluetooth permission denied after request."; + }); + break; + } + break; + } + case PlatformPermissions::PermissionLocalNetwork: { + QLocationPermission permission; + permission.setAccuracy(QLocationPermission::Precise); + + // Status prüfen + auto status = qApp->checkPermission(permission); + + switch (status) { + case Qt::PermissionStatus::Granted: + qCDebug(dcPlatformPermissions()) << "Location permission already granted."; + break; + case Qt::PermissionStatus::Denied: + qCDebug(dcPlatformPermissions()) << "Location permission denied."; + break; + case Qt::PermissionStatus::Undetermined: + qCDebug(dcPlatformPermissions()) << "Location permission not yet requested. Requesting..."; + qApp->requestPermission(permission, [](const QPermission &perm){ + if (perm.status() == Qt::PermissionStatus::Granted) + qCDebug(dcPlatformPermissions()) << "Location permission granted after request."; + else + qCDebug(dcPlatformPermissions()) << "Location permission denied after request."; + }); + break; + } + } + default: + qCWarning(dcPlatformPermissions()) << "Requested status of platform permission" << platformPermission << "but is not implemented yet."; + break; + } + return status; +} + +void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permission platformPermission) +{ + switch (platformPermission) { + case PlatformPermissions::PermissionBluetooth: + qCDebug(dcPlatformPermissions()) << "Requesting bluetooth permission"; + qApp->requestPermission(QLocationPermission{}, [platformPermission](const QPermission &permission) { + if (permission.status() == Qt::PermissionStatus::Denied) { + qCWarning(dcPlatformPermissions()) << "Bluetooth permission denied."; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + } + + if (permission.status() == Qt::PermissionStatus::Granted) + qCDebug(dcPlatformPermissions()) << "Bluetooth permission granted."; + + emit s_instance->bluetoothPermissionChanged(); + }); + break; + case PlatformPermissions::PermissionLocation: { + QLocationPermission locationPermission; + locationPermission.setAccuracy(QLocationPermission::Precise); + qApp->requestPermission(locationPermission, [platformPermission](const QPermission &permission) { + if (permission.status() == Qt::PermissionStatus::Denied) { + qCWarning(dcPlatformPermissions()) << "Location permission denied."; + s_instance->m_requestedButDeniedPermissions.append(platformPermission); + } + + if (permission.status() == Qt::PermissionStatus::Granted) + qCDebug(dcPlatformPermissions()) << "Location permission granted."; + + emit s_instance->locationPermissionChanged(); + }); + break; + } + default: + qCWarning(dcPlatformPermissions()) << "Requested platform permission" << platformPermission << "but is not implemented yet."; + break; + } + + + + emit s_instance->locationPermissionChanged(); + emit s_instance->backgroundLocationPermissionChanged(); + emit s_instance->notificationsPermissionChanged(); + + // if (permissionMap().contains(permission)) { + // qCDebug(dcPlatformPermissions()) << "Requesting permissions:" << permissionMap().value(permission); + + + + // qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) { + + + // if (permission.status() == Qt::PermissionStatus::Granted) + // takePhoto(); + // }); + + // // QtAndroid::requestPermissions({permissionMap().value(permission)}, &permissionResultCallback); + // } +} // void PlatformPermissionsAndroid::openPermissionSettings() // { diff --git a/nymea-app/platformintegration/android/platformpermissionsandroid.h b/nymea-app/platformintegration/android/platformpermissionsandroid.h index d2d872c2..a54d672d 100644 --- a/nymea-app/platformintegration/android/platformpermissionsandroid.h +++ b/nymea-app/platformintegration/android/platformpermissionsandroid.h @@ -1,31 +1,24 @@ -// #ifndef PLATFORMPERMISSIONSANDROID_H -// #define PLATFORMPERMISSIONSANDROID_H +#ifndef PLATFORMPERMISSIONSANDROID_H +#define PLATFORMPERMISSIONSANDROID_H -// #include "../platformpermissions.h" -// #include -// //#include +#include "../platformpermissions.h" +#include -// class PlatformPermissionsAndroid : public PlatformPermissions -// { -// Q_OBJECT -// public: -// explicit PlatformPermissionsAndroid(QObject *parent = nullptr); +class PlatformPermissionsAndroid : public PlatformPermissions +{ + Q_OBJECT +public: + explicit PlatformPermissionsAndroid(QObject *parent = nullptr); -// PermissionStatus checkPermission(Permission permission) const override; + PermissionStatus checkPermission(Permission platformPermission) const override; + void requestPermission(Permission platformPermission) override; -// void requestPermission(Permission permission) override; -// void openPermissionSettings() override; +private: + static PlatformPermissionsAndroid *s_instance; -// signals: + QList m_requestedButDeniedPermissions; + QList m_grantedPermission; -// private: -// QHash permissionMap() const; +}; -// QStringList m_requestedButDeniedPermissions; - -// static PlatformPermissionsAndroid *s_instance; -// // static void permissionResultCallback(const QtAndroid::PermissionResultMap &results); - -// }; - -// #endif // PLATFORMPERMISSIONSANDROID_H +#endif // PLATFORMPERMISSIONSANDROID_H diff --git a/nymea-app/pushnotifications.cpp b/nymea-app/pushnotifications.cpp index 4175879f..87650916 100644 --- a/nymea-app/pushnotifications.cpp +++ b/nymea-app/pushnotifications.cpp @@ -32,11 +32,16 @@ #include "platformhelper.h" #include +#include #if defined Q_OS_ANDROID -#include -#include #include +#include + +#include // QJniEnvironment +#include // QJniObject +#include // QtJniTypes::Context / Activity +#include static PushNotifications *m_client_pointer; #endif @@ -90,12 +95,48 @@ void PushNotifications::registerForPush() qDebug() << "Checking for play services"; jboolean playServicesAvailable = QJniObject::callStaticMethod("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); - }); + + JNIEnv *jni = QJniEnvironment().jniEnv(); + QtJniTypes::Context ctx = QNativeInterface::QAndroidApplication::context(); + jobject contextObj = ctx.object(); + + m_firebaseApp = firebase::App::Create(firebase::AppOptions(), jni, contextObj); + + firebase::messaging::Initialize(*m_firebaseApp, this); + firebase::messaging::SetListener(this); + + // (Optional, Android 13+): Benachrichtigungs-Erlaubnis anfragen + // firebase::messaging::RequestPermission(); + + + + // // Activity + JNIEnv besorgen + // JNIEnv* env = QNativeInterface::QAndroidApplication::jniEnv(); + // jobject activity = QNativeInterface::QAndroidApplication::context(); + + // // Firebase App erstellen + // m_firebaseApp = firebase::App::Create(firebase::AppOptions(), env, activity); + + // // Messaging initialisieren und Listener setzen + // auto initResult = firebase::messaging::Initialize(*m_firebaseApp); + // if (initResult != firebase::kFutureStatusComplete) { + // // optional: warten oder loggen + // } + // firebase::messaging::SetListener(this); + + // // Optional: Token anfordern (wird i.d.R. via OnTokenReceived geliefert) + // firebase::messaging::RequestPermission(); // Android 13+ für Notifications sinnvoll + + + + + // 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."; } diff --git a/packaging/android/AndroidManifest.xml b/packaging/android/AndroidManifest.xml index fec56141..8ec00f45 100644 --- a/packaging/android/AndroidManifest.xml +++ b/packaging/android/AndroidManifest.xml @@ -1,10 +1,23 @@ + + + + + + + + + + + + + + + - - @@ -24,27 +37,6 @@ - - - - - - - - - - - - - - - - - - - - - @@ -72,71 +64,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/android/build.gradle b/packaging/android/build.gradle index f2e95a3e..7644943d 100644 --- a/packaging/android/build.gradle +++ b/packaging/android/build.gradle @@ -87,7 +87,6 @@ android { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = [ qt5AndroidDir + '/src', - nymeaAppRoot + '/androidservice/java', nymeaAppRoot + '/nymea-app/platformintegration/android/java', nymeaAppRoot + '/QtZeroConf/android', 'src',