Android: add SDK 35 support

This commit is contained in:
Simon Stürz 2025-07-14 13:26:21 +02:00
parent 51ad777edd
commit 99ee266ffb
15 changed files with 109 additions and 22 deletions

View File

@ -101,6 +101,11 @@ int main(int argc, char *argv[])
qCInfo(dcApplication()) << "System:" << QSysInfo::machineHostName() << QSysInfo::prettyProductName() << QSysInfo::productType() << QSysInfo::productVersion() << PlatformHelper::instance()->deviceManufacturer() << PlatformHelper::instance()->deviceModel(); qCInfo(dcApplication()) << "System:" << QSysInfo::machineHostName() << QSysInfo::prettyProductName() << QSysInfo::productType() << QSysInfo::productVersion() << PlatformHelper::instance()->deviceManufacturer() << PlatformHelper::instance()->deviceModel();
qCInfo(dcApplication()) << "Locale:" << QLocale() << QLocale().name() << QLocale().language(); qCInfo(dcApplication()) << "Locale:" << QLocale() << QLocale().name() << QLocale().language();
QScreen *screen = application.primaryScreen();
qCInfo(dcApplication()).noquote() << QString("Screen name: %1").arg(screen->name());
qCInfo(dcApplication()).noquote() << QString("Device Pixel Ratio: %1").arg(screen->devicePixelRatio());
qCInfo(dcApplication()).noquote() << QString("Screen Resolution: %1 x %2").arg(screen->geometry().width()).arg(screen->geometry().height());
foreach (const QString &argument, application.arguments()) { foreach (const QString &argument, application.arguments()) {
if (argument.startsWith("nymea://notification")) { if (argument.startsWith("nymea://notification")) {
PlatformHelper::instance()->notificationActionReceived(QUrlQuery(QUrl(argument).query()).queryItemValue("nymeaData")); PlatformHelper::instance()->notificationActionReceived(QUrlQuery(QUrl(argument).query()).queryItemValue("nymeaData"));

View File

@ -90,7 +90,7 @@ 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 = 33 ANDROID_TARGET_SDK_VERSION = 35
QT += androidextras QT += androidextras
HEADERS += platformintegration/android/platformhelperandroid.h \ HEADERS += platformintegration/android/platformhelperandroid.h \
@ -119,6 +119,7 @@ android {
$$ANDROID_PACKAGE_SOURCE_DIR/build.gradle \ $$ANDROID_PACKAGE_SOURCE_DIR/build.gradle \
$$ANDROID_PACKAGE_SOURCE_DIR/gradle/wrapper/gradle-wrapper.properties \ $$ANDROID_PACKAGE_SOURCE_DIR/gradle/wrapper/gradle-wrapper.properties \
$$ANDROID_PACKAGE_SOURCE_DIR/gradlew.bat \ $$ANDROID_PACKAGE_SOURCE_DIR/gradlew.bat \
$$ANDROID_PACKAGE_SOURCE_DIR/gradle.properties \
$$ANDROID_PACKAGE_SOURCE_DIR/LICENSE \ $$ANDROID_PACKAGE_SOURCE_DIR/LICENSE \
platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java \ platformintegration/android/java/io/guh/nymeaapp/NymeaAppActivity.java \
platformintegration/android/java-firebase/io/guh/nymeaapp/NymeaAppNotificationService.java \ platformintegration/android/java-firebase/io/guh/nymeaapp/NymeaAppNotificationService.java \

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -192,6 +192,26 @@ void PlatformHelper::setBottomPanelColor(const QColor &color)
} }
} }
int PlatformHelper::topPadding() const
{
return 0;
}
int PlatformHelper::bottomPadding() const
{
return 0;
}
int PlatformHelper::leftPadding() const
{
return 0;
}
int PlatformHelper::rightPadding() const
{
return 0;
}
bool PlatformHelper::darkModeEnabled() const bool PlatformHelper::darkModeEnabled() const
{ {
return false; return false;

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -58,6 +58,10 @@ class PlatformHelper : public QObject
Q_PROPERTY(bool darkModeEnabled READ darkModeEnabled NOTIFY darkModeEnabledChanged) Q_PROPERTY(bool darkModeEnabled READ darkModeEnabled NOTIFY darkModeEnabledChanged)
Q_PROPERTY(QVariantList pendingNotificationActions READ pendingNotificationActions NOTIFY pendingNotificationActionsChanged) Q_PROPERTY(QVariantList pendingNotificationActions READ pendingNotificationActions NOTIFY pendingNotificationActionsChanged)
Q_PROPERTY(bool locationServicesEnabled READ locationServicesEnabled NOTIFY locationServicesEnabledChanged) Q_PROPERTY(bool locationServicesEnabled READ locationServicesEnabled NOTIFY locationServicesEnabledChanged)
Q_PROPERTY(int topPadding READ topPadding CONSTANT)
Q_PROPERTY(int bottomPadding READ bottomPadding CONSTANT)
Q_PROPERTY(int leftPadding READ leftPadding CONSTANT)
Q_PROPERTY(int rightPadding READ rightPadding CONSTANT)
public: public:
enum HapticsFeedback { enum HapticsFeedback {
@ -88,6 +92,11 @@ public:
virtual QColor bottomPanelColor() const; virtual QColor bottomPanelColor() const;
virtual void setBottomPanelColor(const QColor &color); virtual void setBottomPanelColor(const QColor &color);
virtual int topPadding() const;
virtual int bottomPadding() const;
virtual int leftPadding() const;
virtual int rightPadding() const;
virtual bool darkModeEnabled() const; virtual bool darkModeEnabled() const;
QVariantList pendingNotificationActions() const; QVariantList pendingNotificationActions() const;

View File

@ -27,7 +27,6 @@ public class NymeaAppNotificationService extends FirebaseMessagingService {
private static final String TAG = "nymea-app: NymeaAppNotificationService"; private static final String TAG = "nymea-app: NymeaAppNotificationService";
private int hashId(String id) { private int hashId(String id) {
int hash = 7; int hash = 7;
for (int i = 0; i < id.length(); i++) { for (int i = 0; i < id.length(); i++) {

View File

@ -17,6 +17,9 @@ import android.content.IntentFilter;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.location.LocationManager; import android.location.LocationManager;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
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 org.qtproject.qt5.android.bindings.QtActivity
{ {
@ -40,6 +43,8 @@ public class NymeaAppActivity extends org.qtproject.qt5.android.bindings.QtActiv
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Move th app to the background (Edge to edge is forced since SDK 35)
//WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
this.context = getApplicationContext(); this.context = getApplicationContext();
} }
@ -135,4 +140,15 @@ public class NymeaAppActivity extends org.qtproject.qt5.android.bindings.QtActiv
int mode = Settings.Secure.getInt(getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); int mode = Settings.Secure.getInt(getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
return (mode != Settings.Secure.LOCATION_MODE_OFF); return (mode != Settings.Secure.LOCATION_MODE_OFF);
} }
public int topPadding() {
WindowInsets windowInsets = getWindow().getDecorView().getRootWindowInsets();
return windowInsets.getInsets(WindowInsets.Type.statusBars() | WindowInsets.Type.displayCutout()).top;
}
public int bottomPadding() {
WindowInsets windowInsets = getWindow().getDecorView().getRootWindowInsets();
return windowInsets.getInsets(WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout()).bottom;
}
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -30,12 +30,12 @@
#include "platformhelperandroid.h" #include "platformhelperandroid.h"
#include <QAndroidJniObject>
#include <QtAndroid>
#include <QDebug> #include <QDebug>
#include <QScreen>
#include <QtAndroid>
#include <QAndroidIntent> #include <QAndroidIntent>
#include <QApplication> #include <QApplication>
#include <QAndroidJniObject>
// WindowManager.LayoutParams // WindowManager.LayoutParams
#define FLAG_TRANSLUCENT_STATUS 0x04000000 #define FLAG_TRANSLUCENT_STATUS 0x04000000
@ -86,7 +86,7 @@ PlatformHelperAndroid::PlatformHelperAndroid(QObject *parent) : PlatformHelper(p
} }
connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){ connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
qCritical() << "******* app state change"; qCritical() << "----> Application state changed" << state;
if (state == Qt::ApplicationActive) { if (state == Qt::ApplicationActive) {
emit locationServicesEnabledChanged(); emit locationServicesEnabledChanged();
} }
@ -248,7 +248,26 @@ void PlatformHelperAndroid::setBottomPanelTheme(Theme theme)
visibility &= ~SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; visibility &= ~SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
view.callMethod<void>("setSystemUiVisibility", "(I)V", visibility); 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;
return QtAndroid::androidActivity().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;
return QtAndroid::androidActivity().callMethod<jint>("bottomPadding") / QApplication::primaryScreen()->devicePixelRatio();
} }
bool PlatformHelperAndroid::darkModeEnabled() const bool PlatformHelperAndroid::darkModeEnabled() const

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -60,6 +60,9 @@ public:
void setBottomPanelColor(const QColor &color) override; void setBottomPanelColor(const QColor &color) override;
void setBottomPanelTheme(Theme theme); void setBottomPanelTheme(Theme theme);
int topPadding() const override;
int bottomPadding() const override;
bool darkModeEnabled() const override; bool darkModeEnabled() const override;
bool locationServicesEnabled() const override; bool locationServicesEnabled() const override;

View File

@ -1,12 +1,11 @@
#include "platformpermissionsandroid.h" #include "platformpermissionsandroid.h"
#include <QApplication>
#include <QDebug> #include <QDebug>
#include <QApplication>
#include <QAndroidIntent> #include <QAndroidIntent>
#include <QOperatingSystemVersion> #include <QOperatingSystemVersion>
#include "logging.h" #include "logging.h"
NYMEA_LOGGING_CATEGORY(dcPlatformPermissions, "PlatformPermissions") NYMEA_LOGGING_CATEGORY(dcPlatformPermissions, "PlatformPermissions")
PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr; PlatformPermissionsAndroid * PlatformPermissionsAndroid::s_instance = nullptr;

View File

@ -78,7 +78,6 @@ Page {
header: Item { header: Item {
id: mainHeader id: mainHeader
height: 0 height: 0
HeaderButton { HeaderButton {
id: menuButton id: menuButton
imageSource: "qrc:/icons/navigation-menu.svg" imageSource: "qrc:/icons/navigation-menu.svg"

View File

@ -33,6 +33,7 @@ import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import QtQuick.Window 2.15
import Nymea 1.0 import Nymea 1.0
import NymeaApp.Utils 1.0 import NymeaApp.Utils 1.0
import "components" import "components"
@ -82,6 +83,12 @@ Item {
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: PlatformHelper.topPadding
anchors.bottomMargin: PlatformHelper.bottomPadding
anchors.leftMargin: PlatformHelper.leftPadding
anchors.rightMargin: PlatformHelper.rightPadding
spacing: 0 spacing: 0
SwipeView { SwipeView {

View File

@ -8,7 +8,14 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <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" android:exported="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:windowSoftInputMode="adjustResize"
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"/>

View File

@ -15,7 +15,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.2.2' classpath 'com.android.tools.build:gradle:8.11.0'
classpath 'com.google.gms:google-services:4.3.8' classpath 'com.google.gms:google-services:4.3.8'
} }
} }
@ -39,7 +39,9 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'org.reactivestreams:reactive-streams:1.0.3' implementation 'org.reactivestreams:reactive-streams:1.0.3'
implementation 'io.reactivex.rxjava2:rxjava:2.2.0' implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'androidx.core:core:1.3.2' implementation 'androidx.core:core:1.16.0'
implementation 'androidx.activity:activity:1.10.1'
implementation 'androidx.fragment:fragment:1.8.8'
if ("${useFirebase}" == "true") { if ("${useFirebase}" == "true") {
implementation 'com.google.android.gms:play-services-base:18.1.0' implementation 'com.google.android.gms:play-services-base:18.1.0'
@ -116,5 +118,6 @@ android {
resConfigs "en", "de", "ko", "it", "nl", "es" resConfigs "en", "de", "ko", "it", "nl", "es"
minSdkVersion = 23 minSdkVersion = 23
targetSdkVersion = 35 targetSdkVersion = 35
ndk.abiFilters = qtTargetAbiList.split(",")
} }
} }

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,2 +1,2 @@
1.10.6 1.10.7
671 672