silvansky programming stuff

7Oct/100

сигнал о входящем/исходящем телефонном вызове в Qt под Symbian

в связи с тем, что из QtMobility 1.1 исключили модуль Telephony (анонсированный в 1.1-tp) я немного покопался в инете и нашёл таки способ как поймать начало и конец входящего и исходящего звонков. Осталось поймать смс-ки ;)

итак, средствами Qt этого не сделать. смиритесь. придётся написать немного кода на родном API симбиана.

итак, класс мы назовём CallWatcher. наследовать его мы будем от QObject (чтобы слать сигналы) и от CActive (это уже симбиан, технология Active Object).

  1. class CallWatcher : public QObject, public CActive
  2. {
  3.   Q_OBJECT
  4. public:
  5.   CallWatcher();
  6.   ~CallWatcher();
  7.   void RequestNotification();
  8. private:
  9.   void RunL();
  10.   void DoCancel();
  11. signals:
  12.   void callStarted();
  13.   void callEnded();
  14. private:
  15.   CTelephony* iTelephony;
  16.   CTelephony::TCallStatusV1 iLineStatus;
  17.   CTelephony::TCallStatusV1Pckg iLineStatusPckg;
  18.   bool started;
  19. };

* This source code was highlighted with Source Code Highlighter.

собственно, суть в том, что мы будем ждать сообщения (события, нотификатора, кому как нравится) от объекта класса CTelephony, входящего в библиотеку etel3dparty.

не забываем про инклюды!

#include <e32base.h>
#include <Etel3rdParty.h>
#include <QObject>

* This source code was highlighted with Source Code Highlighter.

первый - для CActive и иже с ним, второй для CTelephony.

теперь пишем сам код:

  1. CallWatcher::CallWatcher(): CActive(EPriorityStandard), QObject(NULL), iLineStatusPckg(iLineStatus)
  2. {
  3.   CActiveScheduler::Add(this);
  4.   iLineStatus.iStatus = CTelephony::EStatusUnknown;
  5.   iTelephony = CTelephony::NewL();
  6.   RequestNotification();
  7.   started = false;
  8. }
  9.  
  10. CallWatcher::~CallWatcher()
  11. {
  12.   delete iTelephony;
  13. }
  14.  
  15. void CallWatcher::RequestNotification()
  16. {
  17.   _LIT(KCallWatcherPanic, "CallWatcher");
  18.   __ASSERT_ALWAYS(!IsActive(), User::Panic(KCallWatcherPanic, 1));
  19.  
  20.   iTelephony->NotifyChange(iStatus, CTelephony::EVoiceLineStatusChange, iLineStatusPckg);
  21.   SetActive();
  22. }
  23.  
  24. void CallWatcher::RunL()
  25. {
  26.   if(iStatus == KErrNone)
  27.   {
  28.     if (!started && (iLineStatus.iStatus != CTelephony::EStatusIdle))
  29.     {
  30.       started = true;
  31.       emit callStarted();
  32.     }
  33.     else if (iLineStatus.iStatus == CTelephony::EStatusIdle)
  34.     {
  35.       started = false;
  36.       emit callEnded();
  37.     }
  38.     RequestNotification();
  39.   }
  40. }
  41.  
  42. void CallWatcher::DoCancel()
  43. {
  44.   iTelephony->CancelAsync(CTelephony::EVoiceLineStatusChangeCancel);
  45. }
  46.  

* This source code was highlighted with Source Code Highlighter.

в конструкторе нашего класса мы сначала добавляем наш объект (CActive*) к шедулеру, т.е., запускаем его на прослушку сообщений.
Затем выставляем статус линии в "неизвестный", создаём объект CTelephony (неудобоваримо на первый взгляд, но так принято в симбиане - двухэтапные конструкторы и прочее), запрашиваем события и помечаем, что разговор не начат ещё.

в функции RequestNotification() мы делаем проверку на валидность (точнее, на активность себя же), а затем запрашиваем у нашего iTelephony нотификатор изменения статуса линии, а затем активизируем себя.

функция RunL() будет вызвана когда придёт нужное нам сообщение. в ней мы проверяем статус на ошибки, и если таковых нет, делаем всё совсем стандартно (не охота подробно комментировать), главное - статус линии хранится в iLineStatus.iStatus. а затем просто запрашиваем следующее событие. так уж сделано там - событие пришло, значит больше не нужно. немного нелогично на мой взгляд, но видимо у разработчиков были свои причины на это.

ну, и для финала делаем функцию отмены DoCancel(), в которой просто отменяем запрос.

всё, теперь можно компилить (не забываем про LIBS += -letel3rdparty в .pro файле) и тестить. в нужный нам момент (входящий или исходящий вызов начат или завершён) мы получим соответствующие сигналы.

стоит отметить, что для использования CTelephony нужны особые капабилитиз - TARGET.CAPABILITY += NetworkServices. но это не помешает тестировать прогу с самоподписанным сертификатом.

Tagged as: , , , , No Comments