Operación del temporizador del sistema operativo Sailfish durante largos intervalos

Introduccion


Muy a menudo, al implementar cualquier lógica en la aplicación, existe la necesidad de activar una determinada función después de un cierto período de tiempo. El ejemplo más obvio de tal necesidad es una aplicación de temporizador. Por ejemplo, temporizador de cocina o Saildoro .

Como se mencionó en un artículo anterior , para agregar un temporizador a una aplicación en Sailfish OS, puede usar el elemento Timer estándar o su contraparte de C ++, QTimer . Sin embargo, de manera predeterminada, el funcionamiento de estos temporizadores se suspende por largos períodos de tiempo debido al hecho de que el dispositivo puede ir a dormir. Los desarrolladores de las dos aplicaciones mencionadas anteriormente acaban de enfrentar este problema.

Este artículo presenta una forma estándar, pero desafortunadamente indocumentada, de manejar este comportamiento del sistema operativo Sailfish.

Punto de partida


Como punto de partida, consideraremos una aplicación "abstracta" para el sistema operativo Sailfish, que requiere la operación de alguna funcionalidad después de un largo período de tiempo. Al mismo tiempo, la operación del temporizador no se describe en el código QML, sino en una clase C ++:

Encabezado
 class TimerWrapper : public QObject { Q_OBJECT public: //    explicit TimerWrapper(QObject *parent = 0); ~TimerWrapper(); Q_INVOKABLE void start(int interval); //     Q_INVOKABLE void stop(); //     signals: void pomodoroFinished(int start, int end); //    void activeChanged(); //     private: QTimer *_timer; //   int _startTime; //    }; 


Fuente
 #include "timerwrapper.h" /** *  . */ TimerWrapper::TimerWrapper(QObject *parent) : QObject(parent) { _timer = new QTimer(this); //    _timer->setSingleShot(true); //     //           connect(_timer, &QTimer::timeout, [=]() { emit activeChanged(); eemit pomodoroFinished(_startTime, QDateTime::currentDateTime().toMSecsSinceEpoch()); }); } /** *  . */ TimerWrapper::~TimerWrapper() { delete _timer; _timer = nullptr; } /** *     . * @:param: interval -      */ void TimerWrapper::start(int interval) { _startTime = QDateTime::currentMSecsSinceEpoch(); //    _timer->start(interval); //   emit activeChanged(); //      } /** *    . */ void TimerWrapper::stop() { _timer->stop(); //   emit activeChanged(); //     } 


Un objeto de esta clase debe estar registrado en QML:

main.cpp
 #ifdef QT_QML_DEBUG #include <QtQuick> #endif #include <QGuiApplication> #include <QQmlContext> #include <QQuickView> #include <QScopedPointer> #include <sailfishapp.h> #include "timerwrapper.h" int main(int argc, char *argv[]) { //    QScopedPointer<QGuiApplication> application(SailfishApp::application(argc, argv)); //      QScopedPointer<QQuickView> view(SailfishApp::createView()); //    QScopedPointer<TimerWrapper> timer(new TimerWrapper(view.data())); //    view->rootContext()->setContextProperty("timer", timer.data()); //     QML- view->setSource(SailfishApp::pathTo("qml/harbour-application.qml")); //   view->show(); //   return application->exec(); } 


Con este enfoque, como se menciona en la introducción, un temporizador puede pausar por largos períodos de tiempo.

Solución


La primera opción para evitar que el temporizador se duerma se propuso en la lista de correo de los desarrolladores y se basó en la aplicación Cooktimer. Aquí se propone configurar explícitamente un temporizador adicional, que una vez por minuto llama al método D-Bus req_display_cancel_blanking_pause para evitar que el dispositivo se duerma. Obviamente, tal implementación no es óptima y engorrosa. En primer lugar, cuando se utiliza este enfoque, la batería del dispositivo se agota más rápido. En segundo lugar, aparece un código menor en el proyecto que se puede evitar.

Y puede evitar el uso de código secundario porque el sistema operativo Sailfish ya proporciona dos posibles soluciones al problema: los elementos ScreenBlank y ScreenBlank .

Usar el primer enfoque implica una pantalla constantemente activa. Este es un enfoque funcional pero directo, que consume activamente la batería del dispositivo. Por lo tanto, se puede usar, pero en un rango limitado de situaciones.

 import QtQuick 2.0 //       QML import Sailfish.Silica 1.0 //     Sailfish OS UI import Sailfish.Media 1.0 //      ScreenBlank ApplicationWindow //     { initialPage: Component { FirstPage { } } //     cover: Qt.resolvedUrl("cover/CoverPage.qml") //    ScreenBlank { //       id: screenBlank //    suspend: true //    } } 

A su vez, usar el elemento KeepAlive es un enfoque más democrático. En menor medida, consume energía de la batería, ya que no mantiene la pantalla del dispositivo constantemente encendida y, al mismo tiempo, no permite que el dispositivo se duerma profundamente o lo despierta en un determinado momento, por lo que el temporizador continuará funcionando. largos períodos de tiempo

 import QtQuick 2.0 //       QML import Sailfish.Silica 1.0 //     Sailfish OS UI import org.nemomobile.keepalive 1.1 //      KeepAlive ApplicationWindow //     { initialPage: Component { FirstPage { } } //     cover: Qt.resolvedUrl("cover/CoverPage.qml") //    KeepAlive { //       id: keepAlive //    enabled: true //       } } 

Vale la pena señalar que, en principio, el funcionamiento de los tres métodos mencionados es una apelación regular a los métodos del sistema de D-Bus, que se discutió en uno de los artículos anteriores .

Conclusión


En esta breve nota, se describen tres formas posibles de evitar que el dispositivo se duerma profundamente. Podemos concluir que para las tareas en segundo plano (por ejemplo, un temporizador) es óptimo usar el elemento KeepAlive , y si es necesario mostrar información constantemente al usuario, ScreenBlank .

Source: https://habr.com/ru/post/es413389/


All Articles