'tizen'에 해당되는 글 3건

  1. 2014.01.12 예제) MultiProcServiceApp, MultiProcUiApp

MultiProcServiceApp, MultiProcUiApp예제는 UI 어플리케이션과 서비스 어플리케이션이 어떻게 커뮤니케이션을 하는지에 대한 방법을 다룬다.


MultiProcServiceApp, MultiProcUiApp예제는 Tizen IDE를 통해 Sample프로젝트를 생성 할 수 있다.


MultiProcServiceApp

MultiProcServiceApp 샘플 어플리케이션은 타이머를 관리하기 위한 UI 어플리케이션(MultiProcUiApp)과 어떻게 통신할수 있는지에 대한 방법을 보여준다. MultiProcServiceApp는 UI(User Interface)를 가지고 있지 않은 서비스 어플리케이션이다. MultiProcServiceApp는 MultiProcUiApp 어플리케이션으로부터 요청을 받아 그에 따라 타이머를 생성하고 시작하고 멈춘다. 


MultiProcUiApp Sample Overview

MultiProcUiApp샘플 어플리케이션은 타이머를 관리하기 위한 서비스어플리케이션(MultiProcServiceApp)과 어떻게 통신할지에 대한 방법을 다룬다.


그림: MultiProcUiApp screens

MultiProcUiApp

MultiProcUiApp 어플리케이션은 타이머와 MultiProcServiceApp 어플리케이션을 연결을 관리 할 수 있는 하나의 화면을 가지고 있다. 


Connect : MultiProcServiceApp과 연결을 한다. 

StartTimer MultiProcServiceApp에게 타이머를 시작하기 위한 요청 메세지를 보낸다.

StopTimer MultiProcServiceApp에게 타이머를 멈추기 위한 요청 메세지를 보낸다.

Exit MultiProcServiceApp와의 연결을 끊는다.


[자세한내용 확인]



Task: Multi Proc Service App

서비스 어플리케이션과 UI어플리케이션간의 통신을 위해서는 Tizen::App 네임스페이스를 이용하여 관리 할 수 있다. 

이 예제는 단방향 메세지 포트 통신 처리양방향 메세지 통신 처리를 기반으로 구축되었으며 다음의 단계로 구성되어있다.


1. To Initialize the Application

a. SampleMessagePort.h 헤더파일 : 어플리케이션과 통신을 위해서는 FIo.h파일을 사용한다.

#include <FApp.h>
#include <FBase.h>
#include <FIo.h>

#include "SampleType.h"


b. Tizen::Io::IMessagePortListener 인터페이스를 선언하여 UI어플리케이션으로부터의 메세지를 들을 수 있도록 한다.

class SampleMessagePort
   : public Tizen::Io::IMessagePortListener
{


c. 리스너 인터페이스와 관련된 이벤트 핸들러를 선언한다.

   public:
      // IMessagePortListener
      virtual void OnMessageReceivedN(Tizen::Io::RemoteMessagePort* pRemoteMessagePort, Tizen::Base::Collection::IMap* pMessage);
      result SendMessage(const Tizen::Base::Collection::IMap* pMessage); 
   // Other variables are declared	
};



2. To Communicate with the UI Application

a. SampleMessagePort.cpp 소스파일

서비스 어플리케이션이 UI어플리케이션으로부터 메세지를 받을때, OnMessageReceiveN() 이벤트 핸들러는 스스로 유저의 이벤트를 서비스 어플리케이션에게 전송하다. 그리고 UI 어플리케이션 메세지에 대해 응답을 한다. 

void
SampleMessagePort::OnMessageReceivedN(RemoteMessagePort* pRemoteMessagePort, IMap* pMessage)
{
   String *pData = static_cast< String* >(pMessage->GetValue(String(L"UiApp")));

   HashMap *pMap = new HashMap(SingleObjectDeleter);
   pMap->Construct();

   if (pData->CompareTo(L"connect") == 0)
   {
      __pRemoteMessagePort = pRemoteMessagePort;
      pMap->Add(new String(L"ServiceApp"), new String(L"ready"));
   }
   else if (pData->CompareTo(L"start") == 0)
   {
      App* pApp = App::GetInstance();
      pApp->SendUserEvent(TIMER_START, null);
      pMap->Add(new String(L"ServiceApp"), new String(L"started"));
   }
   // Other cases for timer stop and application exit requests are defined similarly

   // Sends the response message to the UI application
   pRemoteMessagePort->SendMessage(__pLocalMessagePort, pMap);

   delete pMap;

   delete pMessage;
}



b. SampleServiceApp.cpp 소스파일

유저의 이벤트는 UI어플리케이션을 통해 전달받은 요청에 따라 타이머를 관리하는 OnUserEventReceivedN() 이벤트 핸들러에의해 핸들링 된다.

void
SampleServiceApp::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
   AppLog("SampleServiceApp::OnUserEventReceivedN is called. requestId is %d", requestId);

   switch (requestId)
   {
      case TIMER_START:
         if (__pTimer != null)
         {
            __pTimer->Start();
         }
         break;
      case TIMER_STOP:
         if (__pTimer != null)
         {
            __pTimer->Stop();
         }
         Terminate();
         break;
      case TIMER_EXPIRED:
         if (__pMessagePort != null)
         {
            HashMap *pMap = new HashMap(SingleObjectDeleter);
            pMap->Construct();
            pMap->Add(new String(L"ServiceApp"), new String(L"timer expired"));
            __pMessagePort->SendMessage(pMap);
            delete pMap;
         }
         break;
      case TIMER_EXIT:
         Terminate();
         break;
      default:
         break;
   }
}


c. SampleMessagePort.cpp 소스파일

SendMessage() 메소드는 RemoteMessagePort::SendMessage() 메소드를 이용하여 메세지 포트를 통해 UI 어플리케이션에 응답을 보낸다.

result
SampleMessagePort::SendMessage(const IMap* pMessage)
{
   result r = E_SUCCESS;
   if (__pRemoteMessagePort != null)
   {
      r = __pRemoteMessagePort->SendMessage(__pLocalMessagePort, pMessage);
   }
   else
   {
      // Error handling
   }
   return r;
}


Task: Multi Proc UI App

이 예제는 Tizen::App 네임스페이스를 사용하여 어떻게 서비스 어플리케이션을 실행하고, 서비스 어플리케이션과 UI 어플리케이션간 통신을 처리하는 방법에 대해 다룬다. 


1. To Initialize the Application

a. SampleServiceProxy.h 헤더파일 : FIo.h 헤더 선언

#include <FApp.h>
#include <FBase.h>
#include <FIo.h>


Tizen::Io::IMessagePortListener 인터페이스를 선언하여 서비스 어플리케이션에 대한 응답을 들을수 있도록 한다.

class SampleServiceProxy
   : public Tizen::Io::IMessagePortListener
{


리스너 이벤트와 관련된 이벤트 핸들러를 선언한다.

   public:
      // Constructor and destructor is declared

      result SendMessage(const Tizen::Base::Collection::IMap *pMessage);

      // IMessagePortListener
      virtual void OnMessageReceivedN(Tizen::Io::RemoteMessagePort *pRemoteMessagePort, Tizen::Base::Collection::IMap *pMessage);

   // Other variables are declared	
};


b. SampleUiApp.cpp 소스파일

OnAppInitialized() 이벤트 핸들러는 서비스 어플리케이션와 통신하기 위한 서비스 프록시를 생성한다.

bool
SampleUiApp::OnAppInitialized(void)
{
   AppLog("SampleUiApp: OnAppInitialized is called.");

   // Creates a frame

   String serviceName(L".MultiProcServiceApp");
   String repAppId(15);

   #if MULTI
      GetAppId().SubString(0, 10, repAppId);
   #else
      repAppId = L"hmmql7top4";
   #endif

   AppId serviceId(repAppId+serviceName);

   AppLog("SampleUiApp: Service Id is %ls", serviceId.GetPointer());

   // Initializes a service proxy
   result r = E_SUCCESS;
   __pService = new (std::nothrow) SampleServiceProxy();
   r = __pService->Construct(serviceId, REMOTE_PORT_NAME);

   if (IsFailed(r))
   {
      // Error handling
   }
   else
   {
      __isReady = true;
   }

   return true;
}


c. SampleServiceProxy.cpp 소스파일 

ServiceProxy Construct() 메소드는 서비스 어플리케이션이 동작중인지 아닌지를 체크하고 시작한다. Construct() 메소드는 또한 로컬 메세지 포트 인스턴스를 가져오고 서비스 어플리케이션의 응답을 듣기 위한 인터페이스를 등록한다. 

result
SampleServiceProxy::Construct(AppId appId, const String& remotePortName)
{
   result r = E_FAILURE;

   __appId = appId;

   AppManager* pAppManager = AppManager::GetInstance();

   for (int i=0; i < 5; ++i)
   {
      // If the service application is running
      if (pAppManager->IsRunning(__appId))
      {
         AppLog("SampleUiApp: Service is ready !!!");
         break;
      }
      // If the service application is not running
      else
      {
         r = pAppManager->LaunchApplication(__appId, null);
         Thread::Sleep(CHECK_INTERVAL);
      }
   }

   // Manages the local message port
   __pLocalMessagePort = MessagePortManager::RequestLocalMessagePort(LOCAL_MESSAGE_PORT_NAME);
   __pLocalMessagePort->AddMessagePortListener(*this);

   // Manages the remote message port
   __pRemoteMessagePort = MessagePortManager::RequestRemoteMessagePort(appId, remotePortName);

   return E_SUCCESS;
}


2. To Send Message to the Service Application

a.SampleUiAppMainFrom.cpp 소스파일

유저가 화면에 있는 버튼을 눌렀을때, 유저 이벤트는 OnActionPerformed() 이벤트 핸들러에서 발생한다. 

void
SampleUiAppMainForm::OnActionPerformed(const Control& source, int actionId)
{
   SceneManager* pSceneManager = SceneManager::GetInstance();
   AppAssert(pSceneManager != null);
   App* pApp = App::GetInstance();

   switch (actionId)
   {
      case ID_BUTTON_OK:
         AppLog("SampleUiApp: Button Clicked !!");
         if (pApp != null)
         {
            switch (__current)
            {
               // When the Connect button is clicked
               case STATE_READY:
                  pApp->SendUserEvent(STATE_CONNECT_REQUEST, null);
                  break;
               // When the Start Timer button is clicked
               case STATE_CONNECTED:
                  pApp->SendUserEvent(STATE_TIMER_START_REQUEST, null);
                  break;
               // Other cases are defined similarly
            }
         }
         break;
      default:
         break;
   }
}


b.SampleUiApp.cpp 소스파일

OnUserEventReceivedN 이벤트 핸들러에서 유저의 이벤트가 처리될때, 메세지는 SendMessage() 메소드를 이용하여 서비스 어플리케이션에 보내진다. 

void
SampleUiApp::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
   AppLog("SampleUiApp: OnUserEventReceivedN is called. requestId is %d", requestId);

   result r = E_SUCCESS;

   switch (requestId)
   {
      // When the Connect button is clicked
      case STATE_CONNECT_REQUEST:
         if (__isReady)
         {
            HashMap *pMap = new HashMap(SingleObjectDeleter);
            pMap->Construct();
            pMap->Add(new String(L"UiApp"), new String(L"connect"));

            r = __pService->SendMessage(pMap);

            delete pMap;
         }
         break;
      // When the Start Timer button is clicked
      case STATE_TIMER_START_REQUEST:
         if (__isReady)
         {
            HashMap *pMap = new HashMap(SingleObjectDeleter);
            pMap->Construct();
            pMap->Add(new String(L"UiApp"), new String(L"start"));

            r = __pService->SendMessage(pMap);
            delete pMap;
         }
         break;
      // Other cases are defined similarly
      // Cases for handling the request responses are also defined (described later)
      default:
         break;
   }
}


c.SampleServiceProxy.cpp 소스파일

SendMessage 메소드는 RemoteMessagePort::SendMessage() 메소드를 이용하여 서비스 어플리케이션의 메세지 포트에 요청사항을 전송한다. 

result
SampleServiceProxy::SendMessage(const String message)
{
   if (__pRemoteMessagePort != null)
   {
      r = __pRemoteMessagePort->SendMessage(__pLocalMessagePort, pMessage);      
   }
   else
   {
      // Error handling
   }

   return r;
}


3. To Receive Message from Service Application

a. SampleServiceProxy.cpp 소스파일

서비스 어플리케이션이 응답메세지를 보낼때, OnMessageReceivedN() 이벤트 핸들러가 호출된다. OnMessageReceivedN()이벤트 핸들러는 유저의 이벤트를 UI어플리케이션에 전송한다. 

void
SampleServiceProxy::OnMessageReceivedN(RemoteMessagePort* pRemoteMessagePort, Tizen::Base::Collection::IMap* pMessage)
{
   String key(L"ServiceApp");
   String* pData = static_cast< String* >(pMessage->GetValue(key));

   App* pApp = App::GetInstance();
   if (pData != null && pApp != null)
   {
      if (pData->CompareTo(L"ready") == 0)
      {
         pApp->SendUserEvent(STATE_CONNECTED, null);
      }
      else if (pData->CompareTo(L"started") == 0)
      {
         pApp->SendUserEvent(STATE_TIMER_STARTED, null);
      }
      // Other response options are defined similarly
   }

   delete pMessage;
}


b. SampleUiApp.cpp 소스파일

OnUserEventReceivedN() 이벤트 핸들러에서 유저의 이벤트를 핸들링 할때, 어플리케이션은 유저의 이벤트를 from에 전송을 한다. 

void
SampleUiApp::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
   AppLog("SampleUiApp: OnUserEventReceivedN is called. requestId is %d", requestId);

   result r = E_SUCCESS;

   switch (requestId)
   {
      case STATE_CONNECTED:
         if (__isReady)
         {
            __pForm->SendUserEvent(STATE_CONNECTED, null);
         }
         break;

      case STATE_TIMER_STARTED:
         if (__isReady)
         {
            __pForm->SendUserEvent(STATE_TIMER_STARTED, null);
         }
         break;
      // Other cases are defined similarly
      // Cases for handling the requests are also defined (as described earlier)

   }
}



b. SampleUIAppMainFrom.cpp 소스파일

From은 OnUserEventReceivedN() 이벤트 핸들러를 이용하여 화면상의 버튼의 텍스트라던지 라벨의 상태 등을 업데이트 한다.

void
SampleUiAppMainForm::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
   static int timerCount = 0;

   AppLog("SampleUiApp: OnUserEventReceivedN is called. requestId is %d", requestId);

   Label* pLabel = dynamic_cast< Label* >(GetControl(L"IDC_LABEL1"));
   Button* pButton = dynamic_cast< Button* >(GetControl(L"IDC_BUTTON_OK"));

   switch (requestId)
   {
      // When the application is initialized, 
      // the button is enabled and the label updated
      case STATE_READY:
         if (pLabel != null && pButton != null)
         {
            pLabel->SetText("Ready !!");
            pLabel->Draw(true);
            pButton->SetEnabled(true);
            __current = STATE_READY;
         }
         break;
      // When the connection to the service application is established, 
      // the button text is changed and the label updated	
      case STATE_CONNECTED:
         if (pLabel != null && pButton != null)
         {
            pLabel->SetText("Connected !!");
            pLabel->Draw(true);
            pButton->SetText("Start Timer");
            pButton->Draw(true);
            __current = STATE_CONNECTED;
         }
         break;
      // Cases for other states are defined similarly
   }
}








Posted by No names
,