我正在Android上部署Qt应用程序。它连接BLE设备,接收和记录通知。
当Android设备进入待机状态时,我的应用程序停止接收BLE通知(我不再接收QLowEnergyService::characteristicChanged
信号),当我退出待机状态时,再次收到通知。
我发现这篇文章:How do I prevent an Android device from going to sleep programmatically?,感谢QAndroidJniObject我可以在我的应用程序中实现锁定(请参阅How do I prevent an Android device from going to sleep from Qt application)。
然而:
SCREEN_DIM_WAKE_LOCK
,屏幕将不会进入待机状态并继续接收我的通知。PARTIAL_WAKE_LOCK
,屏幕进入待机状态,但之后我将不会收到我的通知(好像没有实际创建任何锁定)我对SCREEN_DIM_WAKE_LOCK
不满意,因为:
但是,只保持CPU活着(PARTIAL_WAKE_LOCK
应该做什么)是不够的。
我是如何关闭此屏幕并继续接收我的BLE通知的想法?还有其他锁定系统吗? java代码是可以接受的,并且只要它很轻,就可以通过QAndroidJniObject移植到Qt。
我的猜测是你正在获取PARTIAL_WAKE_LOCK,但是当屏幕关闭时,你的应用程序会进入“后台运行”,默认情况下,Qt生成的AndroidManifest.xml会禁用后台运行。
打开“AndroidManifest.xml”文件并切换到“XML Source”。向下滚动并找到此部分:
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="true"/>
<!-- Background running -->
默认情况下,“android.app.background_running”设置为“false”,当屏幕关闭或用户切换到前台运行的不同应用程序时,应用程序执行将暂停。您需要将android.app.background_running设置为“true”,就像我在上面的代码片段中一样。
当您的应用程序在后台运行时,您可能不允许对屏幕进行任何更改,否则会发生意外崩溃。对于我的应用程序,我只显示了一个MainWindow,我似乎可以通过实现这样的applicationStateChanged()槽来避免这个问题:
class MainWindow : public QMainWindow
{
(...)
public slots:
void applicationStateChanged(Qt::ApplicationState state);
}
void MainWindow::applicationStateChanged(Qt::ApplicationState state)
{
if(state != Qt::ApplicationActive)
{
// Don't update GUI if we're not the active application
ui->centralWidget->setVisible(false);
qDebug() << "Hiding GUI because not active state: " << state;
}
else
{
ui->centralWidget->setVisible(true);
qDebug() << "Showing GUI because active now.";
}
}
只要用户关闭屏幕或切换到其他前台应用程序,就会自动调用此函数。
根据我的经验,即使进行了上述更改,您的应用程序仍然可以100%保证运行(您只需要更长一段时间)。 Android似乎有自己的想法,它决定有时会杀掉那些没有在前台运行的进程。也许在高端Android设备上的情况会好于我的情况(我拥有的每台Android设备都有不到1GB的内存)。
请勿将其用于生命支持或其他关键任务情况。
从jpo38编辑,因为主窗口可能是QDialog
或者可能在某个时刻显示QDialog
,禁止重绘这不是更好,而不是隐藏QMainWindow
的中央小部件?:
bool Application::notify(QObject * receiver, QEvent * event)
{
if ( event &&
event->type() == QEvent::Paint )
{
if ( applicationState() != Qt::ApplicationActive )
{
return false;
}
}
return QApplication::notify(receiver,event);
}