Migrating Legacy Platform to Tizen
This topic describes how to convert applications from Samsung Legacy Platform to Tizen.
Related Info
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.
For more information, see Creating Web Applications.
-
Create a new "config.xml" file for your project.
For more information, see Configuring Web Applications.
Ensuring HTML5 Compatibility
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
-
curWidget
object
ThecurWidget
object is not used in Tizen:- Before:
curWidget.id
- After:
tizen.application.getCurrentApplication().appInfo.id
- Before:
-
Log messages
In Tizen, thealert()
method is used to display popup windows. Use theconsole.log()
method to print log messages. -
Viewport configuration
To display an application in fullscreen, set the application width as the viewport width in the "index.html" file:<meta name="viewport" content="width=960" />
For more information, see Managing Screen Resolution.
Setting Content Security Policy
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 thekeydown
event for clicks on an anchor element. In Tizen, use theclick
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.
- If there is only 1 anchor element, in the
-
IME
Tizen provides the IME by default. When aninput
element is focused, the IME appears automatically. You do not need to create the IME using theIMEShell()
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 samekeyValue
enumeration as before, include theTizenTVKeyValue.js
file (direct download).<script src="Common/API/TizenTVKeyValue.js"></script>
// 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:
-
Before:
window.onPause = function() { // pause } window.onResume = function() { // resume }
-
After:
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); }
For more information, see Setting Screensaver.
Playing Media
In Samsung Legacy Platform, media playback was implemented using a plugin
object and the Player API. These are not supported in Tizen.
In Tizen, you can implement media playback in 2 different ways:
- Using the HTML5
video
andaudio
elements
Common media formats can be played using the HTML5video
andaudio
elements. For more information, see Using Video Elements and Using Audio Elements. - Using the AVPlay API from the Samsung Product API
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;
-
-
Event handler implementation:
-
Before:
// load metadata VideoElem.OnStreamInfoReady // time update VideoElem.OnCurrentPlayTime = "Player.OnCurrentPlayTime"; // ended VideoElem.OnRenderingComplete; // buffering event VideoElem.OnBufferingStart = "Player.OnBufferingStart"; VideoElem.OnBufferingComplete = "Player.OnBufferingComplete"; // error VideoElem.OnRenderError = "Player.OnRenderError"; VideoElem.OnStreamNotFound = "Player.OnStreamNotFound"; VideoElem.OnConnectionFailed = "Player.OnConnectionFailed"; VideoElem.OnNetworkDisconnected = "Player.OnNetworkDisconnected";
-
After:
// 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");
-
After:
var str; tizen.filesystem.resolve("wgt-private", function(dir ){ dir.createFile("sample.data"); dir.resolve("wgt-private/sample.data").openStream("rw", function(stream) { stream.write("Something to write."); str = stream.read(100); stream.close(); tizen.filesystem.resolve("wgt-private", function(dir2) { dir2.deleteFile("wgt-private/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.
ImportantThelocalStorage
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 thelocalStorage
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
-