To migrate an application from Samsung Legacy Platform to Tizen, you must import the project to the Tizen Studio, and make the necessary changes in the code.
Importing an Application Project
To import a Samsung Legacy Platform application to Tizen:
Remove the existing "config.xml" and "widget.info" files from the application.
ImportantThe Samsung Legacy Platform "config.xml" file is not compatible with Tizen.
Create the project in the Tizen Studio.
You can do this in 2 different ways:
Create a new Web project in the Tizen Studio using the "Empty" template and copy the existing application files to the new project.
Import the existing Samsung Legacy Platform project to the Tizen Studio as a Tizen Web project.
To import an existing project:
In the Tizen Studio menu, go to "File > Import".
Select "General > Existing Projects into Workspace" and click "Next".
Select the existing project folder or archive file.
To conform to HTML5 standards, modules from the Samsung Legacy Platform Common Modules API, such as the "Widget.js" and "PlugIn.js" libraries, are no longer supported. In Tizen, the Application Manager functionalities are handled using the Application API.
"Widget.js" library
Replace the "Widget.js" library methods with their HTML5 equivalents in Tizen.
Samsung Legacy Platform
Tizen
widgetAPI.putInnerHTML(pdiv,pContents)
pdiv.innerHTML = pContents
widgetAPI.blockNavigation()
event.preventDefault()
widgetAPI.sendReadyEvent()
-
widgetAPI.sendExitEvent()
tizen.application.getCurrentApplication().exit()
widgetAPI.sendReturnEvent()
tizen.application.getCurrentApplication().hide()
Table 1. Tizen equivalents to Samsung Legacy Platform "Widget.js" methods
You must set the content security policy in the "config.xml" file. Tizen supports the W3C standard WARP security rules.
To set the content security policy for the application:
In the "Policy" tab of the configuration editor in the Tizen Studio, add a line to the table by clicking "+".
In the "Network URL" column, enter your server address.
In the "Allow subdomain" column, switch the value to "true" by clicking the table cell.
Ensuring User Interaction
Tizen handles user interaction differently from Samsung Legacy Platform:
Anchor elements
In Samsung Legacy Platform, when mouse devices were not supported, applications registered the keydown event for clicks on an anchor element. In Tizen, use the click event for mouse and remote control clicks.
To migrate key handling on anchor elements to Tizen:
If there is only 1 anchor element, in the body element, register the key handler at the anchor element.
If there are multiple anchor elements, key handlers are needed, but each case can be implemented differently depending on the context.
IME
Tizen provides the IME by default. When an input element is focused, the IME appears automatically. You do not need to create the IME using the IMEShell() method.
For more information on implementing the IME in Tizen, see Keyboard/IME.
Key values
The key values in the Samsung Legacy Platform "TVKeyValue.js" library have changed in Tizen. If you want to continue using the same keyValue enumeration as before, include the TizenTVKeyValue.js file (direct download).
// TizenTVKeyValue.js maps Tizen keyCode values to Legacy Platform' js
// You can use the same "KeyValue" values from the Legacy Platform:
var tvKey = new Common.API.TVKeyValue();
Play/Pause key
The basic remote control was distributed with Samsung TVs until 2014. Since 2015, Samsung Smart TVs are distributed with a Samsung Smart Remote.
The Samsung Smart Remote has a "Play/Pause" key, and you must make sure your Tizen application handles its key clicks correctly. During media playback, clicking the "Play/Pause" key must pause playback, and clicking it while playback is paused must resume playback.
Supporting Multitasking
Multitasking is supported by default on Samsung TVs using Tizen. Unlike in Samsung Legacy Platform, you do not need to configure multitasking in the "config.xml" file. However, you must register an event handler for visibility changes.
The sendReturnEvent(), onPause(), and onResume() methods are not used in Tizen:
document.addEventListener("visibilitychange",
function() {
if (document.hidden) {
// Something you want to do when application is paused
console.log("lifecycle [pause]");
// This code handles playing media when application is hidden
// webapis.avplay.suspend();
}
else {
// Something you want to do when application is resumed
console.log("lifecycle [resume]");
// This code handles playing media when application is visible
// webapis.avplay.restore();
}
}
);
Implementing Screensaver
In Samsung Legacy Platform, the application controlled the screensaver using the setOnScreenSaver() and setOffScreenSaver() methods. The screensaver functionality is handled by the Samsung Product API in Tizen:
Before:
var nnaviPlugin = document.getElementById("pluginObjectNNavi");
// ScreenSaver ON
var screenStateON = 3;
nnaviPlugin.SendEventToDevice(screenStateON, 1);
// ScreenSaver OFF
// var screenStateOFF = 4; //ScreenSaver OFF
// nnaviPlugin.SendEventToDevice(screenStateOFF, 1);
After:
function onsuccess(data) {
console.log("setScreensavervalue = " + data);
}
function onerror(error) {
console.log("error code : " + error.code);
}
try {
// ScreenSaver ON
var screenState = webapis.appcommon.AppCommonScreenSaverState.SCREEN_SAVER_ON;
// ScreenSaver OFF
var screenState = webapis.appcommon.AppCommonScreenSaverState.SCREEN_SAVER_OFF;
var value = webapis.appcommon.setScreenSaver(screenState, onsuccess, onerror);
} catch (error) {
console.log(" error code = " + error.code);
}
The AVPlay API has additional features, such as support for DRM technologies and live streaming. For more information, see Using AVPlay.
To implement media playback with a video element:
Player implementation:
Before:
// getElement
var videoElem = document.getElementById("pluginPlayer");
// setDisplayArea
videoElem.SetDisplayArea(left, top, width, height); // set any value
// init
videoElem.InitPlayer(url); // set your url
// After InitPlayer is called. Seek play to sec.
videoElem.StartPlayback(sec); // set any value
// play
videoElem.Play(url); // set your url
// pause
videoElem.Pause();
// resume
videoElem.Resume();
// stop
videoElem.Stop();
// Rewind / Fast forward
videoElem.JumpForward(sec);
videoElem.JumpBackward(sec);
// get Duration
var duration = videoElem.GetDuration();
// get mute status
var muteStatus = videoElem.GetUserMute();
// set mute
videoElem.SetUserMute(true);
// videoElem.SetUserMute(false);
// set volume
videoElem.SetVolumeWithKey(0);
// get volume
var volume = videoElem.GetVolume();
After:
// getElement
var videoElem = document.createElement("video");
videoElem.style.backgroundColor = "#000";
document.body.appendChild(videoElem);
// setDisplayArea
videoElem.style.left = left + "px"; // set any value
videoElem.style.top = top + "px"; // set any value
videoElem.style.width = width + "px"; // set any value
videoElem.style.height = height + "px"; // set any value
// init
videoElem.src = url; // set your url
videoElem.load();
// Seek play to sec.
if (sec > 0) {
var jumper = function () {
this.currentTime = sec;
this.removeEventListener('loadedmetadata', jumper);
};
videoElem.addEventListener('loadedmetadata', jumper);
}
videoElem.play();
// play
videoElem.src = url; // set your url
videoElem.play();
// pause
videoElem.pause()
// resume
videoElem.play();
// stop
if (videoElem.readyState > 0) {
videoElem.src = '';
}
// Rewind / Fast forward
videoElem.currentTime += sec;
videoElem.currentTime -= sec;
// get Duration
var duration = videoElem.duration * 1000;
// get mute status
var muteStatus = videoElem.muted;
// set mute
videoElem.muted = true;
// videoElem.muted = false;
// set volume (deprecated)
// get volume
var volume = videoElem.volume;
// load metadata
VideoElem.addEventListener('loadedmetadata', function(){}, false);
// time update
VideoElem.addEventListener('timeupdate',function() {
Player.OnCurrentPlayTime(this.currentTime * 1000);
}, false);
// ended
VideoElem.addEventListener('ended', function(){}, false);
// buffering event
var bBuffering = false;
VideoElem.addEventListener("stalled", function(e) {
console.log("stalled");
!bBuffering && Player.OnBufferingStart();
bBuffering = true;
}, false);
VideoElem.addEventListener("waiting", function(e) {
console.log("waiting");
!bBuffering && Player.OnBufferingStart();
bBuffering = true;
}, false);
VideoElem.addEventListener("timeupdate", function(e) {
bBuffering && Player.OnBufferingComplete();
bBuffering = false;
});
// error
VideoElem.addEventListener("error", function(e) {
if (this.getAttribute("src") === "" &&
this.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {
// MEDIA_ERR_SRC_NOT_SUPPORTED occurs
// when changing or initializing source during playback
// Do not treat this as an error
// this.src is not null string but baseURI ("index.html" path)
// Use the getAttribute() method to get the current source
}
else if (this.error && typeof this.error.code === "number") {
switch (this.error.code) {
case MediaError.MEDIA_ERR_ABORTED:
Player.OnConnectionFailed.call(PlayerEvtListener, e);
break;
case MediaError.MEDIA_ERR_ENCRYPTED:
case MediaError.MEDIA_ERR_DECODE:
case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
Player.OnRenderError.call(Player, e);
break;
case MediaError.MEDIA_ERR_NETWORK:
Player.OnNetworkDisconnected.call(Player, e);
break;
default:
PlayerEvtListener.OnRenderError.call(Player, e);
}
}
});
Accessing File System
Samsung Legacy Platform provided 2 file system APIs:
The asynchronous Filesystem API of the WebAPI module
The synchronous FileSystem() method of the Browser API
If you use the asynchronous Filesystem API, you do not need to make changes to the application logic. In Tizen, however, the Filesystem API is no longer part of the WebAPI module but a Tizen API:
Before:
webapis.filesystem.resolve()
After:
tizen.filesystem.resolve()
Tizen does not provide a synchronous file system API. If you used the FileSystem() method, you must change your application implementation in one of the following ways:
Adapt the application logic to use the file system asynchronously and use the Filesystem API:
Before:
var filesystemObj = new FileSystem();
var fileObj = fileSystem.obj.openCommonFile(curWidget.id + "sample.data", "w");
fileObj.writeAll("Something to write.");
var str = fileObj.readAll();
filesystemObj.closeCommonFile(fileObj);
filesystemObj.deleteCommonFile(curwidget.id + "sample.data");
If it is difficult to adapt the synchronous logic to asynchronous logic, you can use the Web standard Web Storage API. For more information, see Using Web Storage.
ImportantThe localStorage object has weak security, as other applications can also access the data. Always use a unique key value, and always encrypt security- or privacy-related data stored in the localStorage object.
Before:
// write data
var fileSystemObj = new FileSystem();
var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/testFile.data', 'w');
fileObj.writeAll('something to write.');
fileSystemObj.closeCommonFile(fileObj);
// read data
var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/testFile.data', 'r');
var strResult = fileObj.readAll();
// delete file
var bResult = fileSystemObj.deleteCommonFile(curWidget.id + '/testFile.data');
// validation check
var bValid = fileSystemObj.isValidCommonPath(curWidget.id);
After:
// write data
localStorage.setItem('testFile', 'something to write.');
// read data
var strResult = localStorage.getItem('testFile');
// delete file
localStorage.removeItem('testFile');
// validation check
// always true
Manage Your Cookies
We use cookies to improve your experience on our website and to show you relevant
advertising. Manage you settings for our cookies below.
Essential Cookies
These cookies are essential as they enable you to move around the website. This
category cannot be disabled.
Company
Domain
Samsung Electronics
.samsungdeveloperconference.com
Analytical/Performance Cookies
These cookies collect information about how you use our website. for example which
pages you visit most often. All information these cookies collect is used to improve
how the website works.
Company
Domain
LinkedIn
.linkedin.com
Meta (formerly Facebook)
.samsungdeveloperconference.com
Google Inc.
.samsungdeveloperconference.com
Functionality Cookies
These cookies allow our website to remember choices you make (such as your user name, language or the region your are in) and
tailor the website to provide enhanced features and content for you.
Company
Domain
LinkedIn
.ads.linkedin.com, .linkedin.com
Advertising Cookies
These cookies gather information about your browser habits. They remember that
you've visited our website and share this information with other organizations such
as advertisers.
Company
Domain
LinkedIn
.linkedin.com
Meta (formerly Facebook)
.samsungdeveloperconference.com
Google Inc.
.samsungdeveloperconference.com
Preferences Submitted
You have successfully updated your cookie preferences.