This page was last modified 13:21, 30 November 2007.
Обнаружение неактивности пользователя в ОС Symbian
From Forum Nokia Wiki
Перевод с английского, оригинальная статья находится здесь.
Contents |
Введение
В данной статье содержится информация о том, как фиксировать активность/бездействие пользователя в Symbian OS.
Представленный здесь активный объект может быть использован для обнаружения событий, возникающих в результате действий пользователя. Под действиями пользователя понимается, например, любое нажатие клавиш.
Для имитации активности пользователя можно использовать следующий вызов:
User::ResetInactivityTime();
Некоторые системные приложений имитируют активность пользователя. Например, при поступлении входящего вызова, имитация активности приводит к исчезновению заставки (хранителя экрана) и, например, к включению подсветки.
Вы тоже можете управлять заставкой и подсветкой в своих приложениях вызывая: ResetInactivityTime().
Для получения информации о времени неактивности пользователя (в секундах) можно использовать следующий вызов:
User::InactivityTime();
Для получения оповещения о прошествии определенного временного интервала бездействия пользователя используется следующий вызов:
Rtimer::Inactivity(TRequestStatus& aStatus, TTimeIntervalSeconds aSeconds);
Этот вызов может быть использован при реализации активного объекта, чья функция RunL() будет вызываться планировщиком по прошествию заданного времени бездействия пользователя.
Такого рода активный объект - основа приложения типа заставки (хранителя экрана). Далее представлен вариант реализации такого активного объекта.
Для реализации используется парадигма обозревателя (observer). Следовательно, вы можете определить логику своего приложения в функциях обратного вызова (callback-функциях) обозревателя (Обозреватель).
Обнаруживать неактивность пользователя в течении заданного временного интервала несложно, однако задача усложняется, если пользователь проявляет активность раньше окончания заданного интервала. Нет соответствующего API для обработки такой ситуации, а периодический вызов User::InactivityTime() может привести к быстрой разрядке аккумулятора. Далее описывается способ (уловка), позволяющий решить данную проблему, немного злоупотребляя семантикой вызова Rtimer::Inactivity().
Реализация
Активный объект, следящий за активностью или неактивностью пользователя, применяет обозреватель (observer), чтобы взаимодействовать с остальным приложением. Объявление обозревателя выглядит так:
class MactivityManagerObserver { public : virtual void ActivityDetected() = 0; virtual void InactivityDetected() = 0; };
В InactivityDetected() Вы описываете, что нужно сделать Вашему приложению, если имела место неактивность. То есть, если Вы пишите экранную заставку, Ваше приложение выйдет на передний план. В ActivityDetected() Вы описываете, что нужно сделать Вашему приложению, когда активность восстановлена, после промежутка времени в неактивности. То есть, если Вы пишите экранную заставку, Ваше приложение уйдет на задний план.
Вот объявление активного объекта:
class CActivityManager : public CActive { public: IMPORT_C static CActivityManager* NewL(MActivityManagerObserver* aObserver, TInt aTimeout = 60); IMPORT_C ~CActivityManager(); IMPORT_C void SetTimeout(TInt aTimeout); IMPORT_C void Start(); IMPORT_C void Reset(); protected: // from CActive void DoCancel(); void RunL(); protected: CActivityManager(MActivityManagerObserver* aObserver, TInt aTimeout); void ConstructL(); protected: enum TWatch { ENone = 0, EWaitingForInactivity, EWaitingForActivity }; protected: RTimer iTimer; TWatch iWatch; MActivityManagerObserver* iObserver; ///Обозреватель статуса активности TInt iTimeout; ///Текущий промежуток времени неактивности };
Вы создаете экземпляр этого активного объекта, вызывая NewL. Вы можете изменить промежуток времени вызывая SetTimeout(). Это тот промежуток времени, после которого (в случае если не было активности пользователя) будет вызван InactivityDetected() в Вашем обозревателе. Вы начинаете следить за активностью пользователя, вызывая Start() и прекращаете делать это, вызывая Reset().
Вызов SetTimeout() всегда будет приводить к перезапуску слежения за неактивностью.
Что насчет реализации, так здесь несколько тривиальных методов:
EXPORT_C CActivityManager* CActivityManager::NewL(MActivityManagerObserver* aObserver, TInt aTimeout) { CActivityManager* self = new (ELeave) CActivityManager(aObserver, aTimeout); CleanupStack::PushL(self); self->ConstructL(); CleanupStack::Pop(self); return self; }
CActivityManager::CActivityManager(MActivityManagerObserver* aObserver, TInt aTimeout) : CActive(CActive::EPriorityHigh), iObserver(aObserver), iTimeout(aTimeout) { CActiveScheduler::Add(this); } EXPORT_C CActivityManager::~CActivityManager() { Cancel(); iTimer.Close(); } void CActivityManager::ConstructL() { iTimer.CreateLocal(); } EXPORT_C void CActivityManager::SetTimeout(TInt aTimeout) { iTimeout = aTimeout; Reset(); } EXPORT_C void CActivityManager::Reset() { Cancel(); Start(); } void CActivityManager::DoCancel() { iTimer.Cancel(); iWatch = ENone; }
Переменная iWatch реализует конечный автомат (машину состояний) активного объекта: либо мы ничего не делаем, либо следим за неактивностью, либо следим за активностью. Основные методы это: Start() и RunL().
Это реализация Start():
EXPORT_C void CActivityManager::Start() { if (!IsActive()) { iWatch = EWaitingForInactivity; iTimer.Inactivity(iStatus, iTimeout); SetActive(); } }
По существу, мы устанавливаем переменную состояния, чтобы следить за неактивностью и запускать оповещение о неактивности, предоставленные Rtimer, определяя желаемые промежутки времени в секундах. RunL() будет выполнен после iSeconds секунд неактивности пользователя. Заметьте, что любой предыдущий промежуток времени неактивности пользователя тоже принимается во внимание. Это означает, что если уже прошло, например, 5 секунд бездействия пользователя, когда мы осуществляем вызов, и мы запрашиваем оповещение после 10-ти секунд неактивности пользователя, то вызов выполниться через 5 секунд, а не через 10.
Ещё одна очень важная вещь, входящая в ядро механизма обнаружения активности пользователя после периода неактивности состоит в том, что что мы не будем оповещены для такого промежутка времени, который меньше чем текущее время неактивности. Чтобы лучше это объяснить: если мы запрашиваем оповещение после 3-х секунд бездействия пользователя, но система уже 6 секунд была неактивна, то мы не будем оповещены пока активность не будет восстановлена и не пройдут следующие 3 секунды бездействия.
Это реализация RunL():
void CActivityManager::RunL() { if (iStatus == KErrNone) { if (iWatch == EWaitingForInactivity) { TInt inactivity = User::InactivityTime().Int(); if (inactivity >= iTimeout) { if (iObserver) { iObserver->InactivityDetected(); } if (!IsActive()) //должно быть обозреватель вызвал Reset() { iTimer.Inactivity(iStatus,0); iWatch = EWaitingForActivity; } } else { iTimer.Inactivity(iStatus,iTimeout); } } else if (iWatch == EWaitingForActivity) { if (iObserver) { iObserver->ActivityDetected(); } if (!IsActive()) // должно быть обозреватель вызвал Reset() { iTimer.Inactivity(iStatus,iTimeout); iWatch = EWaitingForInactivity; } } if (!IsActive()) // должно быть обозреватель вызвал Reset() { SetActive(); } } else { iWatch = ENone; } }
Как видите, это простой бинарный конечный автомат, движущийся от слежения за неактивностью к слежению за активностью и так далее, и вызывающий соответствующие callback-функции обозревателя. После периода неактивности мы используем вызов Rtimer::Inactivity(iStatus, 0), чтобы быть оповещенными о снова наступившей активности. Это уловка (или способ), чтобы обнаружить активность без постоянных User::InactivityTime(). Если уже был любой промежуток неактивности дольше чем 1 секунда, Rtimer::Inactivity(iStatus,0) будет тотчас же выполнен, когда будет восстановлена активность.
| Related Discussions | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Symbian 9.1 -> 9.3 | mmarkuz | General Symbian C++ | 4 | 2006-07-17 12:58 |
| symbian中有vswprintf()么? | linstime | Symbian | 2 | 2008-09-04 03:26 |
| If symbian go to open source, Will you cancel sign symtem? | mzkapoo | General Discussion | 6 | 2008-06-30 16:32 |
| Spy Phone | badabock | General Symbian C++ | 2 | 2007-08-31 19:01 |
| 如何监听串口数据呢 | yinjialiang | Symbian | 6 | 2004-06-10 03:21 |
