아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
--------------------------------------------------------------------------- : https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.appprogramming/html/sample_descriptions/multiprocserviceapp.htm
: https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.appprogramming/html/sample_descriptions/multiprocserviceapp.htm
Tizen에서 ServiceApp과 UiApp간의 interaction을 알 수 있는 샘플
Timer event를 발생 시키는 ServiceApp과 이 ServiceApp에서 event를 받아 Ui에 표시해주는 application sample.
Service와 app간 통신은 IMessagePortListener를 상속받아서 메세지를 주고 받으며 처리한다.
실행해 보려면 Documentation에 나와 있다 시피
service app의 id와 service name을 manifest.xml에서 확인한 뒤
ui app의 SampleUiApp에서 아래 부분을 수정해 줘야 한다.
String serviceName(L".multiprocserviceapp");
String repAppId(15);
repAppId = L"LVjRUjlONC";
AppId serviceId(repAppId+serviceName);
[Tizen::Io::IMessagePortListener]
: https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.apireference/classTizen_1_1Io_1_1IMessagePortListener.html
이것 저것 다 빼고 발로 그린 class diagram
[MultiProcServiceApp]
[SampleServiceApp]
Tizen에서 UI feature를 가지지 않고 background에서 실행될 수 있는 ServiceApp을 상속 받는 class이며 background로 실행되어 Timer를 제어하여 상황 변경 시 event를 app으로 보내주는 것임.
초기화 시점에 App과의 통신을 위한 SampleMessagePort class와 Timer를 제어, event를 발생하는 SampleTimer를 생성하며 SampleMessagePort 생성(construct)시 port name으로 사용할 문자열을 전달하여 port를 생성하도록 한다.
[Message Port Communication]
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/io/messageport.htm
bool
SampleServiceApp::OnAppInitializing(AppRegistry& appRegistry)
{
AppLog("SampleServiceApp::OnAppInitializing is called.");
result r = E_SUCCESS;
// Initialize ServerChannel
__pMessagePort = new (std::nothrow) SampleMessagePort();
TryReturn(__pMessagePort != null, false, "SampleServiceApp : [E_FAILURE] Failed to create __pMessagePort.");
AppLog("SampleServiceApp : __pMessagePort is created.");
r = __pMessagePort->Construct(LOCAL_MESSAGE_PORT_NAME);
TryReturn(IsFailed(r) != true, r, "SampleServiceApp : [%s] Failed to construct __pMessagePort", GetErrorMessage(r));
AppLog("SampleServiceApp : __pMessagePort is constructed.");
// Initialize Timer
__pTimer = new (std::nothrow) SampleTimer;
TryReturn(__pTimer != null, false, "SampleServiceApp : [E_FAILURE] Failed to create __pTimer.");
AppLog("SampleServiceApp : __pTimer is created.");
r = __pTimer->Construct();
TryReturn(IsFailed(r) != true, r, "SampleServiceApp : [%s] Failed to construct __pTimer", GetErrorMessage(r));
AppLog("SampleServiceApp : __pTimer is constructed.");
return true;
}
아래의 Tizen::Ui::Control의 가상함수인 OnUserEventReceivedN()를 구현 하여
SampleTimer로 부터 전달 받은 event를 App으로 전달한다.
void
SampleServiceApp::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
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;
}
}
[SampleMessagePort]
SampleMessagePort는 message를 수신받기위해 Tizen::Io::IMessagePortListener를 구현하였음.
위 그림에서와 같이 수신받는 port인 local port, 전달하는 port인 remote port를 멤버 변수로 가지고 있어 메시지 수신 및 발송 까지 처리하는 class 임
local port는 MessagePortManager를 통해서 생성하고 remote port는 listener에서 connect가 되었을때 전달 받음.
result
SampleMessagePort::Construct(const String& localPortName)
{
result r = E_SUCCESS;
__pLocalMessagePort = MessagePortManager::RequestLocalMessagePort(localPortName);
__pLocalMessagePort->AddMessagePortListener(*this);
...
return r;
}
void
SampleMessagePort::OnMessageReceivedN(RemoteMessagePort* pRemoteMessagePort, IMap* pMessage)
{
String *pData = static_cast<String *>(pMessage->GetValue(String(L"UiApp")));
AppLog("SampleServiceApp : Received data : %ls", pData->GetPointer());
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"));
}
...
}
result
SampleMessagePort::SendMessage(const IMap* pMessage)
{
...
r = __pRemoteMessagePort->SendMessage(__pLocalMessagePort, pMessage);
...
}
[SampleTimer]
Timer event 수신을 위해서 Tizen::Base::Runtime::ITimerEventListener 를 상속 받음.
Timer가 expire 될 경우 SampleServiceApp으로 TIMER_EXPIRED event를 전달함.
void
SampleTimer::OnTimerExpired(Timer& timer)
{
AppLog("SampleServiceApp : __pTimer is expired.");
if (__isRunning)
{
App* pApp = App::GetInstance();
if (pApp != null)
{
ArrayList messageList;
messageList.Construct();
pApp->SendUserEvent(TIMER_EXPIRED, &messageList);
messageList.RemoveAll(true);
}
if (__isRepeatable)
{
timer.Start(TIMER_INTERVAL_RUN);
}
}
else
{
timer.Start(TIMER_INTERVAL_READY);
}
}
-----------------------------------------------------------------------------------------------------
[MultiProcUiApp]
이것 저것 다 빼고 발로 그린 class diagram
[SampleUiApp]
SampleUiApp에서는 GUI 구성에 필요한 frame과 service와 통신을 위해 사용하는 SampleServiceProxy를 생성한다.
AppId(String일 뿐이다.)를 생성한뒤 SampleServiceProxy 생성 후 초기화 때 인자로 넘겨 준다.
bool
SampleUiApp::OnAppInitialized(void)
{
...
String serviceName(L".MultiProcServiceApp");
String repAppId(15);
repAppId = L"qwertzxcvb";
AppId serviceId(repAppId+serviceName);
AppLog("SampleUiApp : Service Id is %ls", serviceId.GetPointer());
// Initialize ServiceProxy.
result r = E_SUCCESS;
__pService = new (std::nothrow) SampleServiceProxy();
r = __pService->Construct(serviceId, REMOTE_PORT_NAME);
if (IsFailed(r))
{
AppLog("SampleUiApp : [%s] SeviceProxy creation is failed.", GetErrorMessage(r));
__pForm->SendUserEvent(STATE_FAIL, null);
}
else
{
__isReady = true;
}
return true;
}
Service로부터 메시지를 수신 받거나 전송하기 위해
Tizen::Base::Runtime::IEventListener를 구현하였음.
requestId에 따라서 명령을 처리하며 위에서 초기화 때 생성한 SampleServiceProxy를 사용하여
메시지 전송
void
SampleUiApp::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
{
AppLog("SampleUiApp : OnUserEventReceivedN is called. requestId is %d", requestId);
result r = E_SUCCESS;
switch (requestId)
{
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;
TryReturnVoid(!IsFailed(r), "SampleUiApp : [%s] MessagePort Operation is Failed", GetErrorMessage(r));
}
break;
...
}
[SampleServiceProxy]
Tizen::Io::IMessagePortListener 를 상속 받아 port를 생성, 관리하는 class.
초반에는 Service가 동작하는지를 AppManager를 통해서 확인하고 없다면 Service를 실행한다.
그리고 Service에서는 local port를 반들고 remote port는 connect 때 만들어 졌는 것에 반해
여기서는 local port와 remote port를 명시적으로 생성한다.
result
SampleServiceProxy::Construct(const AppId& appId, const String& remotePortName)
{
...
AppManager* pAppManager = AppManager::GetInstance();
...
for (int i=0; i < 5; ++i)
{
if (pAppManager->IsRunning(__appId))
{
AppLog("SampleUiApp : Service is ready !!!");
break;
}
else
{
AppLog("SampleUiApp : Service is not ready !!! try to launch !!! ");
r = pAppManager->LaunchApplication(__appId, null);
TryReturn(!IsFailed(r), r, "SampleUiApp : [%s]", GetErrorMessage(r));
Thread::Sleep(CHECK_INTERVAL);
}
}
...
__pLocalMessagePort = MessagePortManager::RequestLocalMessagePort(LOCAL_MESSAGE_PORT_NAME);
__pLocalMessagePort->AddMessagePortListener(*this);
__pRemoteMessagePort = MessagePortManager::RequestRemoteMessagePort(appId, remotePortName);
...
}
Form이랑 Frame은 일반적이라 생략...
댓글 없음:
댓글 쓰기