jpo38
jpo38

Reputation: 21514

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?

Upvotes: 6

Views: 3906

Answers (3)

user5924708
user5924708

Reputation:

I used the solution of S.M. 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();
             }
         }
     }

Upvotes: 1

S.M.Mousavi
S.M.Mousavi

Reputation: 5226

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.

Upvotes: 1

jpo38
jpo38

Reputation: 21514

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.

Upvotes: 9

Related Questions