简体   繁体   中英

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

I'm deploying a Qt application on Android and need to prevent the device from going to standby (else, my threads are interrupted and also my BLE connection gets lost).

I found that on SO: How do I prevent an Android device from going to sleep programmatically?

This Java code should be executed:

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

But how to implement that in my Qt application?

QAndroidJniObject helps executing Java code from Qt. Writting it could be hard and it's hard to figure out what's wrong when it does not work....

Here is the solution (encapsulated in a helper class) to lock a PowerManager.WakeLock object:

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

Then, simply do:

{
    KeepAwakeHelper helper;
    // screen and CPU will stay awake during this section
    // lock will be released when helper object goes out of scope
}

Note: You need to be sure you have the WAKE_LOCK permission set in your manifest in order to use this code.

Another solution:

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

I suggest you to read this question for educational purpose.

I used the solution of SM Mousavi but the app kept crashing. From the same source you have to add some more line of code. Here the complete solution for convenience:

In the .pro file add:

QT += androidextras
ANDROID_PERMISSIONS += android.permission.WAKE_LOCK

I am not sure that the line concerning the permission is really needed.

In your CCP file: add these two includes:

#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>

And where you need:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM