如何防止Android设备从Qt应用程序进入睡眠状态

How do I prevent an Android device from going to sleep from Qt application

本文关键字:状态 应用程序 Qt Android 何防止      更新时间:2023-10-16

我正在Android上部署一个Qt应用程序,需要防止设备进入待机状态(否则,我的线程会中断,BLE连接也会丢失)。

我在SO上发现了这一点:我如何通过程序防止安卓设备进入睡眠状态?

应该执行以下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应用程序中实现呢?

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权限。

另一个解决方案:

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);
    }
}

来源于此处

我建议你读这个问题是为了教育目的。

我使用了S.M.Mousavi的解决方案,但应用程序一直崩溃。从同一个源代码中,您必须添加更多的代码行。这里是方便的完整解决方案:

在.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();
             }
         }
     }