Operação do temporizador Sailfish OS por longos intervalos

1. Introdução


Muitas vezes, ao implementar qualquer lógica no aplicativo, é necessário disparar uma determinada função após um certo período de tempo. O exemplo mais óbvio dessa necessidade é um aplicativo de timer. Por exemplo, cooktimer ou Saildoro .

Como mencionado em um artigo anterior , para adicionar um timer a um aplicativo no Sailfish OS, você pode usar o elemento Timer padrão ou seu equivalente em C ++, QTimer . No entanto, por padrão, a operação desses temporizadores é suspensa por longos períodos de tempo devido ao fato de o dispositivo entrar em suspensão. Os desenvolvedores dos dois aplicativos mencionados acima acabaram de enfrentar esse problema.

Este artigo apresenta uma maneira padrão, mas infelizmente não documentada, de lidar com esse comportamento do sistema operacional Sailfish.

Ponto de partida


Como ponto de partida, consideraremos um aplicativo "abstrato" para o sistema operacional Sailfish, que requer a operação de algumas funcionalidades após um longo período de tempo. Ao mesmo tempo, a operação do timer é descrita não no código QML, mas em uma classe C ++:

Cabeçalho
 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; //    }; 


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


Um objeto desta classe deve ser registrado na 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(); } 


Com essa abordagem, conforme mencionado na introdução, um cronômetro pode pausar por longos períodos de tempo.

Solução


A primeira opção para impedir que o timer adormecesse foi proposta na lista de discussão dos desenvolvedores e se enraizou no aplicativo cooktimer. Aqui, propõe-se configurar explicitamente um cronômetro adicional, que a cada minuto chama o método D-Bus req_display_cancel_blanking_pause para impedir que o dispositivo adormeça. Obviamente, essa implementação não é ótima e complicada. Em primeiro lugar, ao usar essa abordagem, a bateria do dispositivo se esgota mais rapidamente. Em segundo lugar, um código menor aparece no projeto que pode ser evitado.

E você pode evitar o uso de código secundário, pois o Sailfish OS já oferece duas soluções possíveis para o problema: elementos ScreenBlank e KeepAlive .

Usar a primeira abordagem implica uma tela constantemente ativa. Essa é uma abordagem prática, mas direta, que consome ativamente a energia da bateria do dispositivo. Assim, ele pode ser usado, mas em um intervalo limitado de situações.

 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 //    } } 

Por sua vez, o uso do elemento KeepAlive é uma abordagem mais democrática. Em menor grau, consome energia da bateria, pois não mantém a tela do dispositivo constantemente ligada e, ao mesmo tempo, não permite que o dispositivo entre em sono profundo ou o acorda em um determinado momento, para que o temporizador continue a funcionar. longos períodos de tempo.

 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 ressaltar que, em princípio, a operação dos três métodos mencionados é um apelo regular aos métodos de sistema do D-Bus, discutidos em um dos artigos anteriores .

Conclusão


Nesta breve nota, são descritas três maneiras possíveis de impedir que o dispositivo adormeça profundamente. Podemos concluir que, para tarefas em segundo plano (por exemplo, um cronômetro), é ideal usar o elemento KeepAlive e, se houver necessidade de exibir informações constantemente para o usuário, o ScreenBlank .

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


All Articles