Message Port

Overview

This article demonstrates the usage of Message Port Device API for communication between WebApplication to WebApplication and WebApplication to Native Application. For more information on Message port go through the Tizen help link. For more details on Messaging go though the link https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html.

Message Port Device Port provides two types of ports:

LocalMessagePort

A Native/Web Application has to register to LocalMessagePort to receive messages from other Applications.

RemoteMessagePort

A Native/Web Application uses RemoteMessagePort to send messages to other Native/Web Application.

Web to Web Communication

MessagePort Client Application

In this sample, the application user can exchange messages between two web applications like pipes and sockets programming models. For this client, the application registers a Port "WEB_LOCAL_PORT" to receive messages from other application and registers callback to receive messages. The callback API returns a remote port also, where client application uses this port to send messages to the called application.

var localPort = tizen.messageport.requestLocalMessagePort("WEB_LOCAL_PORT");
var localPortWatchId = localPort.addMessagePortListener(function(data, remote)
{
   data.forEach(function(item)
   {
     $("#Msgs").append('<p>' + item.value + '</p>' );
     var remotePort = tizen.messageport.requestRemoteMessagePort('ItrxfbL8qq.MessagePortApplication', remote.messagePortName);
     var MsgString = "Received "+ item.value ;
     remotePort.sendMessage(  [  {key:"Msg", value:MsgString},]);
   });
});

Message Port Chat Application

Html Page

The chat application contains input and button to send messages to client application.

<table>
  <tr>
    <td>
      <input type="text" id="inputField" />
    </td>
    <td>
      <div data-role="button" onclick="sendMessage()">Send</div>
    </td>
  </tr>
</table>
Javascript code

Once user enters messages and clicks send button, the text input field is sent to the client Web Application. For this, RemoteMessagePort needs to be aware of the client Application id UPgEpKpVy4.MessagePortClient and Port Name WEB_LOCAL_PORT to send message by using sendMessage.

webRemoteMsgPort =  tizen.messageport.requestRemoteMessagePort('UPgEpKpVy4.MessagePortClient', 'WEB_LOCAL_PORT');
var data = [{key:'Msg', value:  $('#inputField').val()}];
document.getElementById("inputField").value='';
webRemoteMsgPort.sendMessage(data, webLocalMsgPort);

MessagePort API provides support to share the Web Application local port id to client appplication to send response to server application . The code for creating LocalMessagePort and registering callback is given below.

webLocalMsgPort = tizen.messageport.requestLocalMessagePort("WEB_PORT_RESPONSE");
webLocalMsgPort.addMessagePortListener(function(data, remote){
  data.forEach(function(item)
  {
     $("#msgs").append("<p>" + item.value + "</p>") ;
  });
})

Web to Native Client Application

In this sample, the user can change the device notification, media and ringtone volume through a web application. Tizen SDK doesn't support direct access to system hardware controls. For this, hybrid application is created to communicate with native application using Message Port.

Volume Controller Hybrid Application

Html Page

The Web Page contains the slider controls to change media volumes for notification, system and ringtones. The code for controls is shown below.

<div data-role="content"gt;
<p>Change Volume using Hybrid Application</p>
<div>
  <h4>Notification Volume Control</h4>
  <input id="notification" data-popupenabled="false" type="range" value="0" min="0" max="15" />
</div>
<div>
  <h4>System Volume Control</h4>
  <input id="system" data-popupenabled="false" type="range" value="0" min="0" max="15" />
</div>
<div>
<h4>Ringtone Volume Control</h4>
<input id="ringtone" data-popupenabled="false" type="range" value="0" min="0" max="15" />
</div>
</div>
</divgt;
JavaScript

The Application register the callback for change event for slider to update media volumes.

$("#notification").on("change", function(val ){
	console.log("inside jquery function "+ $("#slider6").val()) ;
	updateVolume("Notification", $("#notification").val() ) ;
});
$("#system").on("change", function(val ){
	console.log("inside jquery function "+ $("#slider6").val()) ;
	updateVolume("System,", $("#system").val() ) ;
});
$("#ringtone").on("change", function(val ){
	console.log("inside jquery function "+ $("#slider6").val()) ;
	updateVolume("Ringtone", $("#ringtone").val() ) ;
});

To change the media controls volume, the web application first launches the native service app using the below code and sends the volume to the native client using the message ports. The code for RemoteMessagePort and SendMessage is shown below.

function LaunchNativeService() {
	try {
		tizen.application.getAppsContext(onGetAppsContextSuccess, onGetAppsContextError);
	} catch (exc) {
		console.log("Get AppContext Error");
	}
}
function onGetAppsContextSuccess(contexts) {
	for (var i = 0; i < contexts.length; i++) {
		var appInfo = tizen.application.getAppInfo(contexts[i].appId);
		//console.log("appinfo"+ appInfo.id);
		if(appInfo.id == gServiceAppId){
			console.log("Running Service App found");
			ServiceAppFound=true;
			break;
		}
	}
	if (ServiceAppFound) {
		initMessagePort();
	}else{
		console.log("Service app not ready, will launch the service now");
		launchServiceApp();
	}	

}

function initMessagePort()
{
	console.log("initMessagePort");
	remoteMsgPort = tizen.messageport.requestRemoteMessagePort(gServiceAppId, 'NATIVE_LOCAL_PORT');
	localMsgPort = tizen.messageport.requestLocalMessagePort("SAMPLE_PORT_RESPONSE");
	localMsgPort.addMessagePortListener(function(data, remote){
		data.forEach(function(item)
		{
			if( item.value=="Success")
				alert("Update"+ item.key+ "Volume Successfuly" );
			else
				alert("Failed to update"+ item.key+ "Volume" );
		});		  

	} );
}
function launchServiceApp() {
	function onSuccess() {
		console.log("Service App launched successfully!");
		// Now initialize the message ports
		console.log("Initializing message ports");
		initMessagePort();
	}

	function onError(err) {
		console.log("Service Applaunch failed");
		isStarting = false;
	}

	try {
		console.log("Launching [" + gServiceAppId + "]");
		tizen.application.launch(gServiceAppId, onSuccess, onError);
	} catch (exc) {
		alert("launch exc:" + exc.message);
	}
}
function updateVolume( systemkey, volume)
{

	console.log("inside updateNotifyVolume" + systemkey + volume ) ;	

	remoteMsgPort.sendMessage(
			[
			 { key:systemkey, value:volume }
			 ], localMsgPort );	

}

Native Volume Control Service

To change the media volume setVolume API of System Info is used. This API requires key and value to set the volume. The below table lists the key values for notification, system and ringtone.

Media Key
Notification http://tizen.org/setting/sound.notification.volume
System http://tizen.org/setting/sound.system.volume
Ringtone http://tizen.org/setting/sound.ringtone.volume

Native Service

For native service to listen to MessagePorts, the class has to be inherited from Tizen::Io::IMessagePortListener and OnMessageReceivedN callback is called when the Web Application sends array data to native service. To change the system data, SetValue method of SystemInfo api is called.

void
MessagePortServiceApp::OnMessageReceivedN(Tizen::Io::RemoteMessagePort* pRemoteMessagePort, Tizen::Base::Collection::IMap* pMessage)
{
	bool isExists ;
	String key;
	String *value;
	String returnKey ;
	pMessage->ContainsKey(String(L"Notification"), isExists);
	if(isExists == true )
	{
		returnKey = L"Notification" ;
		key=L"http://tizen.org/setting/sound.notification.volume";
		value = static_cast (pMessage->GetValue(String(L"Notification")));
	}
	else
	{
		AppLog("-------LakshmiElse");
		pMessage->ContainsKey(String(L"System"), isExists);
		if(isExists == false )
		{
			returnKey = L"Ringtone" ;
			key=L"http://tizen.org/setting/sound.ringtone.volume";
			value = static_cast (pMessage->GetValue(String(L"Ringtone")));
		}
		else
		{
			returnKey = L"System" ;
			key=L"http://tizen.org/setting/sound.system.volume";
			value = static_cast (pMessage->GetValue(String(L"System")));

		}
	}
	result r = setVolume( key, *value) ;
	String res;
	if(r == E_SUCCESS)
	{
		res = L"Success";
	}
	else
		res = L"Failure";

	HashMap* pMap = new HashMap(SingleObjectDeleter);
	pMap->Construct();
	pMap->Add(returnKey, res);
	pRemoteMessagePort->SendMessage( __pLocalMessagePort,  pMap);
}

result
MessagePortServiceApp::setVolume(String &key, String&value)
{
	result r = E_SUCCESS;
	int volume ;
	AppLog("Before Parsing Value");
	Tizen::Base::Integer::Parse( value,volume);
	r = SettingInfo::SetValue(key, volume);
	return r ;
}

Screenshots