diff --git a/plugins/channelrx/heatmap/readme.md b/plugins/channelrx/heatmap/readme.md
index 98f6ff568..1df03df96 100644
--- a/plugins/channelrx/heatmap/readme.md
+++ b/plugins/channelrx/heatmap/readme.md
@@ -8,9 +8,11 @@ To view the Heat Map visually, the [Map Feature](../../feature/map/readme.md) sh
To record data for a heat map, a GPS is required, and Preferences > My Position should have "Auto-update from GPS" enabled.
-On Android, GPS setup should be automatic. On Windows/Linux/Mac, a GPS supporting NMEA via a serial port at 4800 baud is required.
+On Windows/Linux/Mac, a GPS supporting NMEA via a serial port at 4800 baud is required.
The COM port / serial device should be specfied via the QT_NMEA_SERIAL_PORT environment variable before SDRangel is started.
+On Android, GPS setup should be automatic. GPS position updates may stop on Android when the screen is off. To keep the screen on, press the View > Keep Screen On menu.
+
![A Heat Map](../../../doc/img/HeatMap_plugin_map.png)
Interface
diff --git a/sdrbase/maincore.cpp b/sdrbase/maincore.cpp
index bbe70eb9c..43f73ec61 100644
--- a/sdrbase/maincore.cpp
+++ b/sdrbase/maincore.cpp
@@ -28,6 +28,9 @@
#include "device/deviceset.h"
#include "device/deviceapi.h"
#include "channel/channelapi.h"
+#ifdef ANDROID
+#include "util/android.h"
+#endif
#include "maincore.h"
@@ -75,6 +78,9 @@ MainCore::MainCore()
m_masterElapsedTimer.start();
// Position can take a while to determine, so we start updates at program startup
initPosition();
+#ifdef ANDROID
+ QObject::connect(this, &MainCore::deviceStateChanged, this, &MainCore::updateWakeLock);
+#endif
}
MainCore::~MainCore()
@@ -394,3 +400,26 @@ void MainCore::positionError(QGeoPositionInfoSource::Error positioningError)
{
qWarning() << "MainCore::positionError: " << positioningError;
}
+
+#ifdef ANDROID
+// On Android, we want to prevent the app from being put to sleep, when any
+// device is running
+void MainCore::updateWakeLock()
+{
+ bool running = false;
+ for (int i = 0; i < m_deviceSets.size(); i++)
+ {
+ if (m_deviceSets[i]->m_deviceAPI->state() == DeviceAPI::StRunning)
+ {
+ running = true;
+ break;
+ }
+ }
+ if (running) {
+ Android::acquireWakeLock();
+ } else {
+ Android::releaseWakeLock();
+ }
+}
+#endif
+
diff --git a/sdrbase/maincore.h b/sdrbase/maincore.h
index d2dfe0576..c7672b2af 100644
--- a/sdrbase/maincore.h
+++ b/sdrbase/maincore.h
@@ -892,6 +892,9 @@ public slots:
void positionUpdated(const QGeoPositionInfo &info);
void positionUpdateTimeout();
void positionError(QGeoPositionInfoSource::Error positioningError);
+#ifdef ANDROID
+ void updateWakeLock();
+#endif
signals:
void deviceSetAdded(int index, DeviceAPI *device);
diff --git a/sdrbase/util/android.cpp b/sdrbase/util/android.cpp
index 62d74d0a9..955fd6104 100644
--- a/sdrbase/util/android.cpp
+++ b/sdrbase/util/android.cpp
@@ -155,8 +155,6 @@ void Android::closeUSBDevice(int fd)
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
if (activity.isValid()) {
activity.callMethod("closeUSBDevice", "(I)V", fd);
- } else {
- qCritical() << "MainCore::closeUSBDevice: activity is not valid.";
}
}
}
@@ -169,6 +167,38 @@ void Android::moveTaskToBack()
}
}
+void Android::acquireWakeLock()
+{
+ QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
+ if (activity.isValid()) {
+ activity.callMethod("acquireWakeLock");
+ }
+}
+
+void Android::releaseWakeLock()
+{
+ QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
+ if (activity.isValid()) {
+ activity.callMethod("releaseWakeLock");
+ }
+}
+
+void Android::acquireScreenLock()
+{
+ QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
+ if (activity.isValid()) {
+ activity.callMethod("acquireScreenLock");
+ }
+}
+
+void Android::releaseScreenLock()
+{
+ QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
+ if (activity.isValid()) {
+ activity.callMethod("releaseScreenLock");
+ }
+}
+
#endif // QT6
// Redirect qDebug/qWarning to Android log, so we can view remotely with adb
diff --git a/sdrbase/util/android.h b/sdrbase/util/android.h
index ef97d5eed..945076afd 100644
--- a/sdrbase/util/android.h
+++ b/sdrbase/util/android.h
@@ -36,6 +36,10 @@ public:
static void closeUSBDevice(int fd);
static void moveTaskToBack();
static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
+ static void acquireWakeLock();
+ static void releaseWakeLock();
+ static void acquireScreenLock();
+ static void releaseScreenLock();
};
diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp
index efa2f96af..5ade12109 100644
--- a/sdrgui/mainwindow.cpp
+++ b/sdrgui/mainwindow.cpp
@@ -1637,6 +1637,12 @@ void MainWindow::createMenuBar(QToolButton *button)
fullscreenAction->setToolTip("Toggle fullscreen view");
fullscreenAction->setCheckable(true);
QObject::connect(fullscreenAction, &QAction::triggered, this, &MainWindow::on_action_View_Fullscreen_toggled);
+#ifdef ANDROID
+ QAction *keepscreenonAction = viewMenu->addAction("&Keep screen on");
+ keepscreenonAction->setToolTip("Prevent screen from switching off");
+ keepscreenonAction->setCheckable(true);
+ QObject::connect(keepscreenonAction, &QAction::triggered, this, &MainWindow::on_action_View_KeepScreenOn_toggled);
+#endif
QAction *newWorkspaceAction = workspacesMenu->addAction("&New");
newWorkspaceAction->setToolTip("Add a new workspace");
@@ -2183,6 +2189,17 @@ void MainWindow::removeEmptyWorkspaces()
#endif
}
+#ifdef ANDROID
+void MainWindow::on_action_View_KeepScreenOn_toggled(bool checked)
+{
+ if (checked) {
+ Android::acquireScreenLock();
+ } else {
+ Android::releaseScreenLock();
+ }
+}
+#endif
+
void MainWindow::on_action_View_Fullscreen_toggled(bool checked)
{
if(checked) {
diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h
index 6243a241f..5af37cc08 100644
--- a/sdrgui/mainwindow.h
+++ b/sdrgui/mainwindow.h
@@ -179,6 +179,9 @@ private slots:
void handleMessages();
void handleWorkspaceVisibility(Workspace *workspace, bool visibility);
+#ifdef ANDROID
+ void on_action_View_KeepScreenOn_toggled(bool checked);
+#endif
void on_action_View_Fullscreen_toggled(bool checked);
void on_action_saveAll_triggered();
void on_action_Configurations_triggered();