Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Обнаружение неактивности пользователя в ОС Symbian

From Wiki
Jump to: navigation, search
Article Metadata

Статья
Перевод:
Carbider
Последнее редактирование: hamishwillee (09 Dec 2011)
----

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) будет тотчас же выполнен, когда будет восстановлена активность.

This page was last modified on 9 December 2011, at 02:02.
190 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×