如何防止 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/c++ 中集成线程

如何防止根设备绕过 Android 中的证书固定?

从命令行开发适用于 Android 的 Qt 应用程序

当我使用Qt Android Extras C ++ Classes时,如何防止Windows上的错误

C++图形用户界面开发框架Qt 6.1入门级教程 - 入门指南

在 Qt 中,如何在 Android 上使用 USB OTG 串行接口?