mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
9 Commits
Kettler-Ra
...
android-no
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4f2613c7a | ||
|
|
1ca3b8a65c | ||
|
|
dbd8fa4a4c | ||
|
|
18c155fed0 | ||
|
|
54e2b4fa7f | ||
|
|
ab73e3dfdd | ||
|
|
1133404e87 | ||
|
|
c17852de9c | ||
|
|
ee0d00012a |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -750,7 +750,7 @@ jobs:
|
||||
adb shell pm grant org.cagnulen.qdomyoszwift android.permission.WRITE_EXTERNAL_STORAGE || true
|
||||
|
||||
# Start the main activity
|
||||
adb shell am start -n org.cagnulen.qdomyoszwift/org.cagnulen.qdomyoszwift.CustomQtActivity
|
||||
adb shell am start -n org.cagnulen.qdomyoszwift/org.cagnulen.qdomyoszwift.QtActivity
|
||||
|
||||
# Wait for app to start
|
||||
sleep 60
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||
<application android:hardwareAccelerated="true" android:debuggable="false" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="qdomyos-zwift" android:extractNativeLibs="true" android:icon="@drawable/icon" android:usesCleartextTraffic="true">
|
||||
<activity android:theme="@style/Theme.AppCompat" android:exported="true" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.cagnulen.qdomyoszwift.CustomQtActivity" android:label="QZ" android:launchMode="singleTop">
|
||||
<activity android:theme="@style/Theme.AppCompat" android:exported="true" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="QZ" android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.cagnulen.qdomyoszwift;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsetsController;
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
public class CustomQtActivity extends QtActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Handle Android 16 API 36 WindowInsetsController for fullscreen support
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// Android 11 (API 30) and above - use WindowInsetsController
|
||||
getWindow().setDecorFitsSystemWindows(false);
|
||||
WindowInsetsController controller = getWindow().getDecorView().getWindowInsetsController();
|
||||
if (controller != null) {
|
||||
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
|
||||
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||
}
|
||||
} else {
|
||||
// Fallback for older Android versions (API < 30)
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,6 +779,9 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
|
||||
"registerReceiver",
|
||||
"(Landroid/content/Context;)V",
|
||||
QtAndroid::androidContext().object());
|
||||
|
||||
// Create .nomedia files to hide QZ files from Android gallery
|
||||
createNoMediaFiles();
|
||||
#endif
|
||||
|
||||
bluetoothManager->homeformLoaded = true;
|
||||
@@ -8253,6 +8256,33 @@ QString homeform::getAndroidDataAppDir() {
|
||||
path = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
void homeform::createNoMediaFiles() {
|
||||
QString rootPath = getWritableAppDir();
|
||||
|
||||
// Create .nomedia file in root QZ directory
|
||||
QString noMediaPath = rootPath + QStringLiteral(".nomedia");
|
||||
QFile noMediaFile(noMediaPath);
|
||||
if (!noMediaFile.exists()) {
|
||||
noMediaFile.open(QIODevice::WriteOnly);
|
||||
noMediaFile.close();
|
||||
}
|
||||
|
||||
// Create .nomedia files in all subdirectories
|
||||
QDir rootDir(rootPath);
|
||||
if (rootDir.exists()) {
|
||||
QStringList subDirs = rootDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
for (const QString &subDir : subDirs) {
|
||||
QString subDirPath = rootPath + subDir + QStringLiteral("/");
|
||||
QString subNoMediaPath = subDirPath + QStringLiteral(".nomedia");
|
||||
QFile subNoMediaFile(subNoMediaPath);
|
||||
if (!subNoMediaFile.exists()) {
|
||||
subNoMediaFile.open(QIODevice::WriteOnly);
|
||||
subNoMediaFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
quint64 homeform::cryptoKeySettingsProfiles() {
|
||||
@@ -8268,6 +8298,72 @@ quint64 homeform::cryptoKeySettingsProfiles() {
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
int homeform::getStatusBarHeight() {
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
QAndroidJniObject resources = activity.callObjectMethod("getResources", "()Landroid/content/res/Resources;");
|
||||
if (resources.isValid()) {
|
||||
jint resourceId = resources.callMethod<jint>("getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
|
||||
QAndroidJniObject::fromString("status_bar_height").object<jstring>(),
|
||||
QAndroidJniObject::fromString("dimen").object<jstring>(),
|
||||
QAndroidJniObject::fromString("android").object<jstring>());
|
||||
if (resourceId > 0) {
|
||||
jint result = resources.callMethod<jint>("getDimensionPixelSize", "(I)I", resourceId);
|
||||
qDebug() << "Status bar height (pixels):" << result;
|
||||
return result;
|
||||
} else {
|
||||
qDebug() << "Status bar height resource not found";
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Resources object invalid";
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Activity object invalid";
|
||||
}
|
||||
qDebug() << "Status bar height: returning 0 (fallback)";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int homeform::getAndroidApiLevel() {
|
||||
jint apiLevel = QAndroidJniObject::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
|
||||
qDebug() << "Android API level:" << apiLevel;
|
||||
return apiLevel;
|
||||
}
|
||||
|
||||
QString homeform::getAndroidDebugInfo() {
|
||||
int statusBarHeight = getStatusBarHeight();
|
||||
int apiLevel = getAndroidApiLevel();
|
||||
|
||||
QString info = QString("Android Debug Info:\n");
|
||||
info += QString("API Level: %1\n").arg(apiLevel);
|
||||
info += QString("Status Bar Height: %1px\n").arg(statusBarHeight);
|
||||
|
||||
// Get screen dimensions
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
QAndroidJniObject windowManager = activity.callObjectMethod("getWindowManager", "()Landroid/view/WindowManager;");
|
||||
if (windowManager.isValid()) {
|
||||
QAndroidJniObject display = windowManager.callObjectMethod("getDefaultDisplay", "()Landroid/view/Display;");
|
||||
if (display.isValid()) {
|
||||
QAndroidJniObject metrics = QAndroidJniObject("android/util/DisplayMetrics");
|
||||
display.callMethod<void>("getMetrics", "(Landroid/util/DisplayMetrics;)V", metrics.object());
|
||||
|
||||
int width = metrics.getField<jint>("widthPixels");
|
||||
int height = metrics.getField<jint>("heightPixels");
|
||||
float density = metrics.getField<jfloat>("density");
|
||||
|
||||
info += QString("Screen: %1x%2px\n").arg(width).arg(height);
|
||||
info += QString("Density: %1\n").arg(density);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << info;
|
||||
return info;
|
||||
}
|
||||
#endif
|
||||
|
||||
void homeform::saveSettings(const QUrl &filename) {
|
||||
Q_UNUSED(filename)
|
||||
QString path = getWritableAppDir();
|
||||
|
||||
@@ -521,6 +521,13 @@ class homeform : public QObject {
|
||||
Q_INVOKABLE static QString getProfileDir();
|
||||
Q_INVOKABLE static void clearFiles();
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
static void createNoMediaFiles();
|
||||
Q_INVOKABLE int getStatusBarHeight();
|
||||
Q_INVOKABLE int getAndroidApiLevel();
|
||||
Q_INVOKABLE QString getAndroidDebugInfo();
|
||||
#endif
|
||||
|
||||
double wattMaxChart() {
|
||||
QSettings settings;
|
||||
if (bluetoothManager && bluetoothManager->device() &&
|
||||
|
||||
30
src/main.qml
30
src/main.qml
@@ -13,10 +13,18 @@ ApplicationWindow {
|
||||
id: window
|
||||
width: 640
|
||||
height: 480
|
||||
visibility: Qt.WindowFullScreen
|
||||
visibility: (OS_VERSION === "Android" && statusBarOffset > 0) ? Qt.WindowMaximized : Qt.WindowFullScreen
|
||||
visible: true
|
||||
objectName: "stack"
|
||||
title: qsTr("qDomyos-Zwift")
|
||||
|
||||
// Android status bar offset (only for Android API 31+ / Android 12+)
|
||||
property int statusBarOffset: {
|
||||
if (OS_VERSION === "Android" && rootItem.getAndroidApiLevel() >= 31) {
|
||||
return rootItem.getStatusBarHeight()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
signal gpx_open_clicked(url name)
|
||||
signal gpxpreview_open_clicked(url name)
|
||||
@@ -47,6 +55,23 @@ ApplicationWindow {
|
||||
|
||||
property bool lockTiles: false
|
||||
property bool settings_restart_to_apply: false
|
||||
|
||||
// Debug Android status bar
|
||||
property int androidApiLevel: 0
|
||||
property int statusBarHeight: 0
|
||||
|
||||
Component.onCompleted: {
|
||||
if(OS_VERSION === "Android") {
|
||||
console.log("Calling Android debug functions...")
|
||||
try {
|
||||
androidApiLevel = rootItem.getAndroidApiLevel()
|
||||
statusBarHeight = rootItem.getStatusBarHeight()
|
||||
console.log("Debug values set: API=" + androidApiLevel + ", StatusBar=" + statusBarHeight)
|
||||
} catch (e) {
|
||||
console.log("Error calling Android functions:", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
@@ -909,6 +934,7 @@ ApplicationWindow {
|
||||
id: stackView
|
||||
initialItem: "Home.qml"
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: statusBarOffset
|
||||
focus: true
|
||||
Keys.onVolumeUpPressed: (event)=> { console.log("onVolumeUpPressed"); volumeUp(); event.accepted = settings.volume_change_gears; }
|
||||
Keys.onVolumeDownPressed: (event)=> { console.log("onVolumeDownPressed"); volumeDown(); event.accepted = settings.volume_change_gears; }
|
||||
@@ -924,5 +950,5 @@ ApplicationWindow {
|
||||
|
||||
event.accepted = settings.volume_change_gears;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user