Start porting android

qt6-qmake-android
Simon Stürz 2025-10-15 15:02:56 +02:00
parent fa0a96211a
commit 00b3a6fcbd
16 changed files with 265 additions and 247 deletions

4
.gitmodules vendored
View File

@ -1,11 +1,11 @@
[submodule "QtZeroConf"]
path = QtZeroConf
url = https://github.com/mzanetti/QtZeroConf.git
url = https://github.com/jbagg/QtZeroConf.git
[submodule "nymea-remoteproxy"]
path = nymea-remoteproxy
url = https://github.com/guh/nymea-remoteproxy.git
[submodule "android_openssl"]
path = 3rdParty/android/android_openssl
url = https://github.com/KDAB/android_openssl.git
branch = 1.0.x
branch = master
shallow = true

View File

@ -1,7 +1,7 @@
TEMPLATE = lib
TARGET = service
CONFIG += dll
QT += core androidextras
QT += core core-private
QT += network qml quick quickcontrols2 svg websockets bluetooth charts nfc
include(../shared.pri)

View File

@ -14,7 +14,7 @@
#include <QtDebug>
#include <QtQml>
#include <QtAndroid>
#include <QAndroidJniObject>
#include <QJniObject>
#include <QAndroidIntent>
#include <QNdefNfcUriRecord>

View File

@ -4,7 +4,7 @@
#include <QDebug>
#include <QAndroidParcel>
#include <QAndroidJniObject>
#include <QJniObject>
#include <QJsonDocument>
#include <QtAndroid>
@ -111,5 +111,5 @@ bool AndroidBinder::onTransact(int code, const QAndroidParcel &data, const QAndr
void AndroidBinder::sendReply(const QAndroidParcel &reply, const QVariantMap &params)
{
QString payload = QJsonDocument::fromVariant(params).toJson();
reply.handle().callMethod<void>("writeString", "(Ljava/lang/String;)V", QAndroidJniObject::fromString(payload).object<jstring>());
reply.handle().callMethod<void>("writeString", "(Ljava/lang/String;)V", QJniObject::fromString(payload).object<jstring>());
}

View File

@ -78,6 +78,6 @@ void NymeaAppService::sendNotification(const QString &notification, const QVaria
QString payload = QJsonDocument::fromVariant(data).toJson();
QtAndroid::androidService().callMethod<void>("sendBroadcast",
"(Ljava/lang/String;)V",
QAndroidJniObject::fromString(payload).object<jstring>());
QJniObject::fromString(payload).object<jstring>());
}

View File

@ -1,9 +1,9 @@
#ifndef NYMEAAPPSERVICE_H
#define NYMEAAPPSERVICE_H
#include <QAndroidService>
#include <QNearFieldManager>
#include <QNdefMessage>
#include <QtCore/private/qandroidextras_p.h>
#include "engine.h"

View File

@ -10,8 +10,8 @@ include(../../shared.pri)
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
LIBS += -L$${top_builddir}/libnymea-app/$${ANDROID_TARGET_ARCH}
PRE_TARGETDEPS += $$top_builddir/libnymea-app/$${ANDROID_TARGET_ARCH}/libnymea-app.a
}
INCLUDEPATH += $${top_srcdir}/libnymea-app/

View File

@ -51,23 +51,23 @@ ZeroconfDiscovery::ZeroconfDiscovery(NymeaHosts *nymeaHosts, QObject *parent) :
connect(m_zeroconfJsonRPC, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfJsonRPC, &QZeroConf::serviceRemoved, this, &ZeroconfDiscovery::serviceEntryRemoved);
if (m_zeroconfJsonRPC->isValid()) {
// if (m_zeroconfJsonRPC->isValid()) {
m_zeroconfJsonRPC->startBrowser("_jsonrpc._tcp", QAbstractSocket::IPv4Protocol);
qCInfo(dcZeroConf()) << "Created service browser for _jsonrpc._tcp:" << m_zeroconfJsonRPC->browserExists();
} else {
qCWarning(dcZeroConf()) << "Failed to initialize service broeser for _jsonprc._tcp";
}
// } else {
// qCWarning(dcZeroConf()) << "Failed to initialize service broeser for _jsonprc._tcp";
// }
m_zeroconfWebSocket = new QZeroConf(this);
connect(m_zeroconfWebSocket, &QZeroConf::serviceAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfWebSocket, &QZeroConf::serviceUpdated, this, &ZeroconfDiscovery::serviceEntryAdded);
connect(m_zeroconfWebSocket, &QZeroConf::serviceRemoved, this, &ZeroconfDiscovery::serviceEntryRemoved);
if (m_zeroconfWebSocket->isValid()) {
// if (m_zeroconfWebSocket->isValid()) {
m_zeroconfWebSocket->startBrowser("_ws._tcp", QAbstractSocket::IPv4Protocol);
qCInfo(dcZeroConf()) << "Created service browser for _ws._tcp:" << m_zeroconfWebSocket->browserExists();
} else {
qCWarning(dcZeroConf()) << "Failed to initialize service browserr for _ws._tcp";
}
// } else {
// qCWarning(dcZeroConf()) << "Failed to initialize service browserr for _ws._tcp";
// }
#else
qCInfo(dcZeroConf()) << "Zeroconf support not compiled in. Zeroconf will not be available.";

View File

@ -81,8 +81,8 @@ linux:!android: {
android: {
message("Android package source dir $${ANDROID_PACKAGE_SOURCE_DIR}")
SUBDIRS += androidservice
androidservice.depends = libnymea-app
# SUBDIRS += androidservice
# androidservice.depends = libnymea-app
NYMEA_APP_ROOT_PROPERTY="nymeaAppRoot=$${top_srcdir}"
no-firebase: FIREBASE_PROPERTY="useFirebase=false"

View File

@ -92,7 +92,6 @@ android {
ANDROID_MIN_SDK_VERSION = 21
ANDROID_TARGET_SDK_VERSION = 35
QT += androidextras
HEADERS += platformintegration/android/platformhelperandroid.h \
platformintegration/android/platformpermissionsandroid.h \

View File

@ -32,10 +32,9 @@
#include <QDebug>
#include <QScreen>
#include <QtAndroid>
#include <QAndroidIntent>
#include <QtCore/private/qandroidextras_p.h>
#include <QApplication>
#include <QAndroidJniObject>
#include <QJniObject>
// WindowManager.LayoutParams
#define FLAG_TRANSLUCENT_STATUS 0x04000000
@ -70,20 +69,27 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
return JNI_VERSION_1_6;
}
static QAndroidJniObject getAndroidWindow()
{
QAndroidJniObject window = QtAndroid::androidActivity().callObjectMethod("getWindow", "()Landroid/view/Window;");
return window;
}
// static QJniObject getAndroidWindow()
// {
// QJniObject window;
// QJniObject activity = QNativeInterface::QAndroidApplication::context();
// if(activity.isValid()) {
// activity.callMethod<void>("setRequestedOrientation", "(I)V", 0);
// window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
// }
// // QJniObject window = QNativeInterface::QAndroidApplication::context().callMethod<jobject>("getWindow", "()Landroid/view/Window;");
// return window;
// }
PlatformHelperAndroid::PlatformHelperAndroid(QObject *parent) : PlatformHelper(parent)
{
m_instance = this;
QString notificationData = QtAndroid::androidActivity().callObjectMethod("notificationData", "()Ljava/lang/String;").toString();
if (!notificationData.isNull()) {
notificationActionReceived(notificationData);
}
// QString notificationData = QNativeInterface::QAndroidApplication::context().callMethod<jstring>("notificationData", "()Ljava/lang/String;").toString();
// if (!notificationData.isNull()) {
// notificationActionReceived(notificationData);
// }
connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
qCritical() << "----> Application state changed" << state;
@ -98,7 +104,7 @@ void PlatformHelperAndroid::hideSplashScreen()
// Android's splash will flicker when fading out twice
static bool alreadyHiding = false;
if (!alreadyHiding) {
QtAndroid::hideSplashScreen(250);
//QtAndroid::hideSplashScreen(250);
alreadyHiding = true;
}
}
@ -111,23 +117,23 @@ QString PlatformHelperAndroid::machineHostname() const
QString PlatformHelperAndroid::deviceSerial() const
{
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
return activity.callObjectMethod<jstring>("deviceSerial").toString();
}
QString PlatformHelperAndroid::device() const
{
return QAndroidJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","device").toString();
return QJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","device").toString();
}
QString PlatformHelperAndroid::deviceModel() const
{
return QAndroidJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","deviceModel").toString();
return QJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","deviceModel").toString();
}
QString PlatformHelperAndroid::deviceManufacturer() const
{
return QAndroidJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","deviceManufacturer").toString();
return QJniObject::callStaticObjectMethod<jstring>("io/guh/nymeaapp/NymeaAppActivity","deviceManufacturer").toString();
}
void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType)
@ -145,7 +151,23 @@ void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType
break;
}
QtAndroid::androidActivity().callMethod<void>("vibrate","(I)V", duration);
QJniObject context = QNativeInterface::QAndroidApplication::context();
if (!context.isValid()) {
qDebug() << "Could not get Android context.";
return;
}
QJniObject vibrator = context.callMethod<jobject>("getSystemService", "Landroid/content/Context;Ljava/lang/String;", QJniObject::fromString("vibrator").object());
if (!vibrator.isValid()) {
qDebug() << "Could not get vibrator service.";
return;
}
// Call the vibrate method
vibrator.callMethod<void>("vibrate", "(J)V", duration);
//QtAndroid::androidActivity().callMethod<void>("vibrate","(I)V", duration);
}
//void PlatformHelperAndroid::syncThings()
@ -153,7 +175,7 @@ void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType
// QAndroidIntent serviceIntent(QtAndroid::androidActivity().object(),
// "io/guh/nymeaapp/NymeaAppService");
// QAndroidJniObject result = QtAndroid::androidActivity().callObjectMethod(
// QJniObject result = QtAndroid::androidActivity().callObjectMethod(
// "startService",
// "(Landroid/content/Intent;)Landroid/content/ComponentName;",
// serviceIntent.handle().object());
@ -169,7 +191,7 @@ void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType
//// m_serviceConnection->handle().callMethod<void>("syncThings", "(Ljava/lang/String;)V", "bla");
//// QAndroidJniObject result = QtAndroid::androidActivity().callObjectMethod(
//// QJniObject result = QtAndroid::androidActivity().callObjectMethod(
//// "syncThings",
//// "(Landroid/content/Intent;)Landroid/content/ComponentName;",
//// m_serviceConnection->handle().object());
@ -179,113 +201,118 @@ void PlatformHelperAndroid::setTopPanelColor(const QColor &color)
{
PlatformHelper::setTopPanelColor(color);
if (QtAndroid::androidSdkVersion() < 21)
return;
// if (QtAndroid::androidSdkVersion() < 21)
// return;
QtAndroid::runOnAndroidThread([=]() {
QAndroidJniObject window = getAndroidWindow();
window.callMethod<void>("addFlags", "(I)V", FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.callMethod<void>("clearFlags", "(I)V", FLAG_TRANSLUCENT_STATUS);
window.callMethod<void>("setStatusBarColor", "(I)V", color.rgba());
});
// QtAndroid::runOnAndroidThread([=]() {
// QJniObject window = getAndroidWindow();
// window.callMethod<void>("addFlags", "(I)V", FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// window.callMethod<void>("clearFlags", "(I)V", FLAG_TRANSLUCENT_STATUS);
// window.callMethod<void>("setStatusBarColor", "(I)V", color.rgba());
// });
if (((color.red() * 299 + color.green() * 587 + color.blue() * 114) / 1000) > 123) {
setTopPanelTheme(Light);
} else {
setTopPanelTheme(Dark);
}
// if (((color.red() * 299 + color.green() * 587 + color.blue() * 114) / 1000) > 123) {
// setTopPanelTheme(Light);
// } else {
// setTopPanelTheme(Dark);
// }
}
void PlatformHelperAndroid::setBottomPanelColor(const QColor &color)
{
PlatformHelper::setBottomPanelColor(color);
if (QtAndroid::androidSdkVersion() < 21)
return;
// if (QtAndroid::androidSdkVersion() < 21)
// return;
QtAndroid::runOnAndroidThread([=]() {
QAndroidJniObject window = getAndroidWindow();
window.callMethod<void>("clearFlags", "(I)V", FLAG_TRANSLUCENT_NAVIGATION);
window.callMethod<void>("setNavigationBarColor", "(I)V", color.rgba());
// QtAndroid::runOnAndroidThread([=]() {
// QJniObject window = getAndroidWindow();
// window.callMethod<void>("clearFlags", "(I)V", FLAG_TRANSLUCENT_NAVIGATION);
// window.callMethod<void>("setNavigationBarColor", "(I)V", color.rgba());
if (((color.red() * 299 + color.green() * 587 + color.blue() * 114) / 1000) > 123) {
setBottomPanelTheme(Light);
} else {
setBottomPanelTheme(Dark);
}
});
// if (((color.red() * 299 + color.green() * 587 + color.blue() * 114) / 1000) > 123) {
// setBottomPanelTheme(Light);
// } else {
// setBottomPanelTheme(Dark);
// }
// });
}
void PlatformHelperAndroid::setTopPanelTheme(PlatformHelperAndroid::Theme theme)
{
if (QtAndroid::androidSdkVersion() < 23)
return;
Q_UNUSED(theme)
// if (QtAndroid::androidSdkVersion() < 23)
// return;
QtAndroid::runOnAndroidThread([=]() {
QAndroidJniObject window = getAndroidWindow();
QAndroidJniObject view = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
int visibility = view.callMethod<int>("getSystemUiVisibility", "()I");
if (theme == Theme::Light)
visibility |= SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
else
visibility &= ~SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
view.callMethod<void>("setSystemUiVisibility", "(I)V", visibility);
});
// QtAndroid::runOnAndroidThread([=]() {
// QJniObject window = getAndroidWindow();
// QJniObject view = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
// int visibility = view.callMethod<int>("getSystemUiVisibility", "()I");
// if (theme == Theme::Light)
// visibility |= SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
// else
// visibility &= ~SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
// view.callMethod<void>("setSystemUiVisibility", "(I)V", visibility);
// });
}
void PlatformHelperAndroid::setBottomPanelTheme(Theme theme)
{
if (QtAndroid::androidSdkVersion() < 23)
return;
Q_UNUSED(theme)
QtAndroid::runOnAndroidThread([=]() {
QAndroidJniObject window = getAndroidWindow();
QAndroidJniObject view = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
int visibility = view.callMethod<int>("getSystemUiVisibility", "()I");
if (theme == Theme::Light)
visibility |= SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
else
visibility &= ~SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
view.callMethod<void>("setSystemUiVisibility", "(I)V", visibility);
});
// if (QtAndroid::androidSdkVersion() < 23)
// return;
// QtAndroid::runOnAndroidThread([=]() {
// QJniObject window = getAndroidWindow();
// QJniObject view = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
// int visibility = view.callMethod<int>("getSystemUiVisibility", "()I");
// if (theme == Theme::Light)
// visibility |= SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
// else
// visibility &= ~SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
// view.callMethod<void>("setSystemUiVisibility", "(I)V", visibility);
// });
}
int PlatformHelperAndroid::topPadding() const
{
// Edge to edge has been forced since android SDK 35
// We don't want to handle it in earlied versions.
if (QtAndroid::androidSdkVersion() < 35)
return 0;
// if (QtAndroid::androidSdkVersion() < 35)
// return 0;
return QtAndroid::androidActivity().callMethod<jint>("topPadding") / QApplication::primaryScreen()->devicePixelRatio();
return QNativeInterface::QAndroidApplication::context().callMethod<jint>("topPadding") / QApplication::primaryScreen()->devicePixelRatio();
}
int PlatformHelperAndroid::bottomPadding() const
{
// Edge to edge has been forced since android SDK 35
// We don't want to handle it in earlied versions.
if (QtAndroid::androidSdkVersion() < 35)
return 0;
// if (QtAndroid::androidSdkVersion() < 35)
// return 0;
return QtAndroid::androidActivity().callMethod<jint>("bottomPadding") / QApplication::primaryScreen()->devicePixelRatio();
return QNativeInterface::QAndroidApplication::context().callMethod<jint>("bottomPadding") / QApplication::primaryScreen()->devicePixelRatio();
}
bool PlatformHelperAndroid::darkModeEnabled() const
{
return QtAndroid::androidActivity().callMethod<jboolean>("darkModeEnabled");
return QNativeInterface::QAndroidApplication::context().callMethod<jboolean>("darkModeEnabled");
}
bool PlatformHelperAndroid::locationServicesEnabled() const
{
jboolean enabled = QtAndroid::androidActivity().callMethod<jboolean>("locationServicesEnabled", "()Z");
return enabled;
// jboolean enabled = QNativeInterface::QAndroidApplication::context().callMethod<jboolean>("locationServicesEnabled", "()Z");
// return enabled;
return true;
}
void PlatformHelperAndroid::shareFile(const QString &fileName)
{
QtAndroid::androidActivity().callMethod<void>("shareFile", "(Ljava/lang/String;)V",
QAndroidJniObject::fromString(fileName).object<jstring>()
);
Q_UNUSED(fileName)
// QNativeInterface::QAndroidApplication::context().callMethod<void>("shareFile", "(Ljava/lang/String;)V",
// QJniObject::fromString(fileName).object<jstring>()
// );
}
void PlatformHelperAndroid::darkModeEnabledChangedJNI()

View File

@ -34,8 +34,9 @@
#include "platformhelper.h"
#include <QObject>
#include <QtAndroid>
#include <QAndroidServiceConnection>
#include <QJniObject>
#include <QJniEnvironment>
#include <QtCore/private/qandroidextras_p.h>
class PlatformHelperAndroid : public PlatformHelper
{
@ -73,8 +74,6 @@ public:
static void notificationActionReceivedJNI(JNIEnv *env, jobject /*thiz*/, jstring data);
static void locationServicesEnabledChangedJNI();
private:
static void permissionRequestFinished(const QtAndroid::PermissionResultMap &);
};
#endif // PLATFORMHELPERANDROID_H

View File

@ -1,122 +1,121 @@
#include "platformpermissionsandroid.h"
// #include "platformpermissionsandroid.h"
#include <QDebug>
#include <QApplication>
#include <QAndroidIntent>
#include <QOperatingSystemVersion>
// #include <QDebug>
// #include <QApplication>
// #include <QOperatingSystemVersion>
#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);
}
}
// void PlatformPermissionsAndroid::requestPermission(PlatformPermissions::Permission permission)
// {
// if (permissionMap().contains(permission)) {
// qCDebug(dcPlatformPermissions()) << "Requesting permissions:" << permissionMap().value(permission);
// QtAndroid::requestPermissions({permissionMap().value(permission)}, &permissionResultCallback);
// }
// }
void PlatformPermissionsAndroid::openPermissionSettings()
{
qCDebug(dcPlatformPermissions()) << "Opening permission dialog.";
QAndroidJniObject packageName = QtAndroid::androidContext().callObjectMethod("getPackageName", "()Ljava/lang/String;");
QString packageUri = "package:" + packageName.toString();
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", QAndroidJniObject::fromString(packageUri).object());
QAndroidIntent intent = QAndroidIntent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.handle().callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object());
intent.handle().callObjectMethod("addFlags", "(I)Landroid/content/Intent;", FLAG_ACTIVITY_NEW_TASK);
QtAndroid::androidContext().callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.handle().object());
}
// void PlatformPermissionsAndroid::openPermissionSettings()
// {
// qCDebug(dcPlatformPermissions()) << "Opening permission dialog.";
// QJniObject packageName = QtAndroid::androidContext().callObjectMethod("getPackageName", "()Ljava/lang/String;");
// QString packageUri = "package:" + packageName.toString();
// QJniObject uri = QJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", QJniObject::fromString(packageUri).object());
// QAndroidIntent intent = QAndroidIntent("android.settings.APPLICATION_DETAILS_SETTINGS");
// intent.handle().callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object());
// intent.handle().callObjectMethod("addFlags", "(I)Landroid/content/Intent;", FLAG_ACTIVITY_NEW_TASK);
// QtAndroid::androidContext().callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.handle().object());
// }
QHash<PlatformPermissions::Permission, QStringList> PlatformPermissionsAndroid::permissionMap() const
{
QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
if (osVersion.majorVersion() <= 9) {
return {
{PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION"}}
};
}
if (osVersion.majorVersion() <= 10) {
return {
{PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
};
}
if (osVersion.majorVersion() <= 12) {
return {
// TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_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.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
{PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
};
}
return {
// TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_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.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_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"}}
};
}
// QHash<PlatformPermissions::Permission, QStringList> PlatformPermissionsAndroid::permissionMap() const
// {
// QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
// if (osVersion.majorVersion() <= 9) {
// return {
// {PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION"}}
// };
// }
// if (osVersion.majorVersion() <= 10) {
// return {
// {PlatformPermissions::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
// };
// }
// if (osVersion.majorVersion() <= 12) {
// return {
// // TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_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.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionLocation, {"android.permission.ACCESS_FINE_LOCATION"}},
// {PlatformPermissions::PermissionBackgroundLocation, {"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}}
// };
// }
// return {
// // TODO: Once QtBluetooth does not request the COARSE_LOCATION and FINE_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.BLUETOOTH_ADVERTISE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_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"}}
// };
// }
PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermission(Permission permission) const
{
PermissionStatus status = PermissionStatusGranted;
QStringList androidPermissions = permissionMap().value(permission);
qCDebug(dcPlatformPermissions()) << "Checking permission" << permission << "(" << androidPermissions << ")";
foreach (const QString androidPermission, androidPermissions) {
if (QtAndroid::shouldShowRequestPermissionRationale(androidPermission) || m_requestedButDeniedPermissions.contains(androidPermission)) {
qCDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "denied";
status = PermissionStatusDenied;
}
if (QtAndroid::checkPermission(androidPermission) == QtAndroid::PermissionResult::Denied) {
qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "not determined";
if (status != PermissionStatusDenied) {
status = PermissionStatusNotDetermined;
}
} else {
qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "granted";
}
}
qCDebug(dcPlatformPermissions()) << "Permission status for:" << permission << ":" << status;
return status;
}
// PlatformPermissions::PermissionStatus PlatformPermissionsAndroid::checkPermission(Permission permission) const
// {
// PermissionStatus status = PermissionStatusGranted;
// QStringList androidPermissions = permissionMap().value(permission);
// qCDebug(dcPlatformPermissions()) << "Checking permission" << permission << "(" << androidPermissions << ")";
// foreach (const QString androidPermission, androidPermissions) {
// if (QtAndroid::shouldShowRequestPermissionRationale(androidPermission) || m_requestedButDeniedPermissions.contains(androidPermission)) {
// qCDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "denied";
// status = PermissionStatusDenied;
// }
// if (QtAndroid::checkPermission(androidPermission) == QtAndroid::PermissionResult::Denied) {
// qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "not determined";
// if (status != PermissionStatusDenied) {
// status = PermissionStatusNotDetermined;
// }
// } else {
// qDebug(dcPlatformPermissions()) << "Permission:" << androidPermission << "granted";
// }
// }
// qCDebug(dcPlatformPermissions()) << "Permission status for:" << permission << ":" << status;
// return status;
// }
void PlatformPermissionsAndroid::permissionResultCallback(const QtAndroid::PermissionResultMap &results)
{
foreach (const QString &androidPermission, results.keys()) {
qCDebug(dcPlatformPermissions()) << "Permission result callback:" << androidPermission << (results.value(androidPermission) == QtAndroid::PermissionResult::Granted ? "Granted" : "Denied");
if (results.value(androidPermission) == QtAndroid::PermissionResult::Denied) {
s_instance->m_requestedButDeniedPermissions.append(androidPermission);
}
}
emit s_instance->bluetoothPermissionChanged();
emit s_instance->locationPermissionChanged();
emit s_instance->backgroundLocationPermissionChanged();
emit s_instance->notificationsPermissionChanged();
}
// void PlatformPermissionsAndroid::permissionResultCallback(const QtAndroid::PermissionResultMap &results)
// {
// foreach (const QString &androidPermission, results.keys()) {
// qCDebug(dcPlatformPermissions()) << "Permission result callback:" << androidPermission << (results.value(androidPermission) == QtAndroid::PermissionResult::Granted ? "Granted" : "Denied");
// if (results.value(androidPermission) == QtAndroid::PermissionResult::Denied) {
// s_instance->m_requestedButDeniedPermissions.append(androidPermission);
// }
// }
// emit s_instance->bluetoothPermissionChanged();
// emit s_instance->locationPermissionChanged();
// emit s_instance->backgroundLocationPermissionChanged();
// emit s_instance->notificationsPermissionChanged();
// }

View File

@ -1,31 +1,31 @@
#ifndef PLATFORMPERMISSIONSANDROID_H
#define PLATFORMPERMISSIONSANDROID_H
// #ifndef PLATFORMPERMISSIONSANDROID_H
// #define PLATFORMPERMISSIONSANDROID_H
#include "../platformpermissions.h"
// #include "../platformpermissions.h"
// #include <QtCore/private/qandroidextras_p.h>
// //#include <QtAndroidExtras/QtAndroid>
#include <QtAndroidExtras/QtAndroid>
// 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 permission) const override;
// void requestPermission(Permission permission) override;
// void openPermissionSettings() override;
void requestPermission(Permission permission) override;
void openPermissionSettings() override;
// signals:
signals:
// private:
// QHash<PlatformPermissions::Permission, QStringList> permissionMap() const;
private:
QHash<PlatformPermissions::Permission, QStringList> permissionMap() const;
// QStringList m_requestedButDeniedPermissions;
QStringList m_requestedButDeniedPermissions;
// static PlatformPermissionsAndroid *s_instance;
// // static void permissionResultCallback(const QtAndroid::PermissionResultMap &results);
static PlatformPermissionsAndroid *s_instance;
static void permissionResultCallback(const QtAndroid::PermissionResultMap &results);
// };
};
#endif // PLATFORMPERMISSIONSANDROID_H
// #endif // PLATFORMPERMISSIONSANDROID_H

View File

@ -36,7 +36,7 @@
#if defined Q_OS_ANDROID
#include <QtAndroid>
#include <QtAndroidExtras>
#include <QAndroidJniObject>
#include <QJniObject>
static PushNotifications *m_client_pointer;
#endif
@ -88,7 +88,7 @@ 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");
jboolean playServicesAvailable = QJniObject::callStaticMethod<jboolean>("io.guh.nymeaapp.NymeaAppNotificationService", "checkPlayServices", "()Z");
if (playServicesAvailable) {
qDebug() << "Setting up firebase";
m_client_pointer = this;

View File

@ -3,9 +3,6 @@ greaterThan(QT_MAJOR_VERSION, 5) {
CONFIG *= c++17
QMAKE_LFLAGS *= -std=c++17
QMAKE_CXXFLAGS *= -std=c++17
# Python init is crashing in Qt6,
# disable by default until fixed
CONFIG += withoutpython
} else {
message("Building using Qt5 support")
CONFIG *= c++14
@ -14,7 +11,7 @@ greaterThan(QT_MAJOR_VERSION, 5) {
DEFINES += QT_DISABLE_DEPRECATED_UP_TO=0x050F00
}
#QMAKE_CXXFLAGS *= -Werror -g -Wno-deprecated-declarations
QMAKE_CXXFLAGS *= -Werror -g -Wno-deprecated-declarations
top_srcdir=$$PWD
top_builddir=$$shadowed($$PWD)
@ -40,10 +37,7 @@ INCLUDEPATH += $${top_builddir}
# On Windows, -Wall goes mental, so not using it there
!win32:QMAKE_CXXFLAGS += -Wall
# As of Qt 5.15, lots of things are deprecated inside Qt in preparation for Qt6 but no replacement to actually fix those yet.
linux:!android {
QMAKE_CXXFLAGS += -Wno-deprecated-declarations -Wno-deprecated-copy
}
QMAKE_CXXFLAGS += -Wno-deprecated-declarations -Wno-deprecated-copy
android: {
QMAKE_CXXFLAGS += -Wno-deprecated-declarations