如何防止 Android 设备从 Qt 应用程序进入睡眠状态
Posted
技术标签:
【中文标题】如何防止 Android 设备从 Qt 应用程序进入睡眠状态【英文标题】:How do I prevent an Android device from going to sleep from Qt application 【发布时间】:2016-03-14 18:37:18 【问题描述】:我正在 android 上部署 Qt 应用程序,需要防止设备进入待机状态(否则,我的线程被中断,我的 BLE 连接也会丢失)。
我在 SO:How do I prevent an Android device from going to sleep programmatically?
这个Java代码应该被执行:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
// screen and CPU will stay awake during this section
wl.release();
但是如何在我的 Qt 应用程序中实现呢?
【问题讨论】:
【参考方案1】:QAndroidJniObject 帮助从 Qt 执行 Java 代码。编写它可能很困难,而且当它不起作用时很难找出问题所在....
这里是锁定PowerManager.WakeLock
对象的解决方案(封装在一个帮助类中):
LockHelper.h:
#pragma once
#include <QAndroidJniObject>
class KeepAwakeHelper
public:
KeepAwakeHelper();
virtual ~KeepAwakeHelper();
private:
QAndroidJniObject m_wakeLock;
;
LockHelper.cpp:
#include "LockHelper.h"
#include <QAndroidJniObject>
#include <QDebug>
#include "jni.h"
KeepAwakeHelper::KeepAwakeHelper()
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
if ( activity.isValid() )
QAndroidJniObject serviceName = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Context","POWER_SERVICE");
if ( serviceName.isValid() )
QAndroidJniObject powerMgr = activity.callObjectMethod("getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;",serviceName.object<jobject>());
if ( powerMgr.isValid() )
jint levelAndFlags = QAndroidJniObject::getStaticField<jint>("android/os/PowerManager","SCREEN_DIM_WAKE_LOCK");
QAndroidJniObject tag = QAndroidJniObject::fromString( "My Tag" );
m_wakeLock = powerMgr.callObjectMethod("newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;", levelAndFlags,tag.object<jstring>());
if ( m_wakeLock.isValid() )
m_wakeLock.callMethod<void>("acquire", "()V");
qDebug() << "Locked device, can't go to standby anymore";
else
assert( false );
KeepAwakeHelper::~KeepAwakeHelper()
if ( m_wakeLock.isValid() )
m_wakeLock.callMethod<void>("release", "()V");
qDebug() << "Unlocked device, can now go to standby";
然后,只需这样做:
KeepAwakeHelper helper;
// screen and CPU will stay awake during this section
// lock will be released when helper object goes out of scope
注意:您需要确保在清单中设置了WAKE_LOCK 权限才能使用此代码。
【讨论】:
谢谢你,非常清楚和很有帮助的答案。您可以使用Q_ASSERT(false)
代替assert(false);
【参考方案2】:
另一种解决方案:
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
if (activity.isValid())
QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid())
const int FLAG_KEEP_SCREEN_ON = 128;
window.callMethod<void>("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
Source here
出于教育目的,我建议您阅读this question。
【讨论】:
看到这个主题,无法使用 QAndroidJniObject 将您的解决方案转换为代码。不错的答案【参考方案3】:我使用了 S.M. 的解决方案。穆萨维,但应用程序不断崩溃。在同一个source 中,您必须添加更多代码行。为方便起见,这里是完整的解决方案:
在.pro文件中添加:
QT += androidextras
ANDROID_PERMISSIONS += android.permission.WAKE_LOCK
我不确定是否真的需要有关权限的行。
在您的 CCP 文件中: 添加这两个包括:
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>
你需要的地方:
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
if (activity.isValid())
QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid())
const int FLAG_KEEP_SCREEN_ON = 128;
window.callMethod<void>("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
//Clear any possible pending exceptions.
QAndroidJniEnvironment env;
if (env->ExceptionCheck())
env->ExceptionClear();
【讨论】:
以上是关于如何防止 Android 设备从 Qt 应用程序进入睡眠状态的主要内容,如果未能解决你的问题,请参考以下文章
当我使用Qt Android Extras C ++ Classes时,如何防止Windows上的错误