top

Smart Hub Preview

Samsung TV for Tizen platform supports Preview. There are two ways to implement Preview using server API and Background Service. This document covers the basic features of Preview, terminology and its implementation.

Overview

Preview is available since Tizen platform 2.4 or higher (Samsung TV 2016 models onwards).
Whenever user hovers application on “Smart Hub Launcher”, “Preview” is shown with “Launcher”.
On “Preview”, users can directly see contents and “Deep Link” into the contents of application.

According to our investigations, preview helps to promote most interesting content of the application.
This catch-up content helps to drive more attention to the application.

Note

Implementation of “Preview” functionality is as easy as these three steps:

  • Gather requirements for the tiles and configuration from the documentation
  • Prepare thumbnails and configuration JSON file on the backend side
  • Implement “Deep Link” in the application
Important

Depend on your purpose of application, there are two ways to implement “Preview”.
Please note that you can’t use both ways at the same time.

  • Using Server API : It has a purpose to show preview to everyone with same common preview. The application provides URL to an endpoint returning a JSON describing the Tiles. URL will be queried by tizen platform to set preview DB. Then preview will be shown.
  • Using Background Service : It has a purpose to show personal suitable preview for each different user. The application can run a background process to set preview DB. Then preview will be shown.

Dependencies

Depending on the model of Samsung TV, “Preview” can be supported or not.
Please refer to the following table for detail.

Product Support Model
Samsung TV All of 2016 Samsung TV models onwards
Samsung TV SDK Version 2.3.1 onwards

Terminology

  • "Launcher"
    This is a quick access bar for common functions and applications.

  • "Preview"
    Preview shows a list of “Section”.

    • "Section"
      Tiles can be organized into different “sections” such as “Popular now” and “VOD recommended”.

    • "Tile"
      This is a component of Section.

  • "Deep Link"
    This means to jump from “Preview” to the specific detail page of application when user clicks “Tile”.

Adding Application to Launcher

Preview is shown only when an application is hovered on “Launcher”.
So, the application should be on “Launcher”. The following step is how to place the application on “Launcher”.

  • On “Launcher”, hover “APPS” icon and confirm application icon lists are shown on “Preview”.

  • Navigate to “Preview” and focus the application icon.

  • Click “Up” key and click “Add to Home”.

  • Place the application icon anywhere on “Launcher”.

  • After clicking “Enter” button, confirm “Preview” is shown.

Policy

It covers some regulations of “Preview”. Please refer to the followings before making “Preview”.

All contents in “Preview” are owned by the application and are under contents provider’s responsibility.
But, Preview contents should comply the following things.

  • “Preview” should be used for following purpose:

    • Deep linking into playing contents such as movies, episodes, music or etc.

    • Deep linking into detail pages within application such as lists of episodes within seasons or etc.

    • Deep linking into the authenticate page of application such as account login screen.

    • If using background service, following purpose is also available.

      • Deep linking into personalized service if application is log-in based.

      • Deep linking into playing recent contents initiated by user.

  • It’s not allowed to use “Preview” for:

    • Displaying third party advertisements.

    • Displaying the features or capabilities of application.

  • Different kind of services can have different “Preview” contents, for example:

    • Video / Music service
      Ex) Popular videos / Top picks / Resume playing / My playlist

    • Sports
      Ex) Top games this week / My team

    • Lifestyle service
      Ex) Today’s news / My city’s weather / Hot topic

    • Game service
      Ex) Top games now / Recently played game

UX Guidelines

Section Requirements

  • The following table is “Section” requirements.

    Requirements Description
    The number of Section 1 or more
    The number of Tile in a Section 1 or more
  • The following picture is “Section” image.

  • The following table is about Section elements.

    Element Description
    Title Optional
    (If “Title” text is too long, it is automatically scrolled.)
  • "Title" should be the same as system language.
    To support multiple language, please refer to it in chapter Configure JSON file.

Tile Requirements

  • The following table is “Tile” requirements.

    Requirements Description
    Deep Link URL of Tile It should be different from each other.
    The number of Tile Maximum is 40.
  • The following table is “Tile” requirements for Size.

    Size Description
    Tile height It is fixed at 250px.
    (Thumbnail height should be taller or equal than 250px. If it is taller than, it will be suitably shrunk.)
    Tile width It is 167px, 250px, 333px or 444px.
    Tile Ratio 16:9 (444 x 250px)
    4:3 (333 x 250px)
    1:1 (250 x 250px)
    2:3 (167 x 250px)

    Please refer to the following “Tile” ratio.

  • The following picture is “Tile” image.

  • The following table is about “Tile” elements.

    Element Description
    Thumbnail PNG, JPG
    It should be suitable for viewers of all ages.
    It shouldn’t be broken, or won’t be displayed.
    Maximum image file size is 360KB.
    Title Optional
    It is displayed in bold.
    (If Title text is too long, it is automatically scrolled.)
    Subtitle Optional
    It is displayed below Title.
    (If Subtitle text is too long, it is automatically scrolled.)
    Playable Icon Optional
    It is displayed on upper-right corner.
    If Deep linking into playback, you can show it on Tile.
    Important

    “Title”, “Subtitle” and “Playable Icon” are displayed over hovered “Tile” only.

  • "Title" and “Subtitle” should be the same as system language.
    To support multiple language, please refer to it in chapter Configure JSON file.

Return Scenario

After deep linking from “Preview” into the application,
if user clicks “Return” key, it should navigate back to the previous page within application.
And then, if user clicks on the home page within application, the application should be terminated without any confirmation.

Implementation

Overall

As mentioned overview, there are two ways to implement “Preview”.
Following table describes difference between Server API and Background Service.

Server API Background Service
Populating Tiles Add Endpoint URL which returns JSON data in config.xml Write JSON data using background service
Workload server side > client side server side < client side
Customization X O
Expires option O X

Using Server API

Flow Chart

  • JSON is connected on “config.xml”.

  • “Preview” is shown.

  • If user clicks “Preview”, deep linking is occured.

  • “action_data” in JSON is sent to the application.

  • In the application, “action_data” is parsed. Finally, the detail page is shown.

Configuring JSON File

For “Preview”, the data (“Thumbnail”, “Title”, “action_data” and etc) is needed.
The format of data model is JSON object. Only one JSON file is allowed per application.

JSON File URL should be connected on “config.xml”. Please refer to it in chapter Set “config.xml”.

  • The following table is properties.

    Name Type Required
    expires UTC timestamp Optional
    sections Array Mandatory
    • "expires"
      Server API only. If application uses background service, this property will be ignored.
      By default, “Preview” is refreshed every 10 minutes and when a TV turns on.
      However, if you include “expires” information in JSON, “Preview” doesn’t update until the expiration time.

    • "sections"
      The list of “sections” in “Preview”.

  • The following table is “sections” properties.

    Name Type Required
    title String Optional
    position integer optional
    tiles Array Mandatory
    • "title"
      It is “Section”'s “Title”.

    • "position"
      If you include it in JSON, “sections” is in ascending order of position.

    • "tiles"
      The list of Tiles in the “Section”.

  • The following table is Tiles properties.

    Name Type Required
    title String Optional
    subtitle String Optional
    image_url String Mandatory
    image_ratio String Mandatory
    action_data String Mandatory
    is_playable Boolean Mandatory
    display_from UTC timestamp Optional
    display_until UTC timestamp Optional
    position Integer Optional
    • "title"
      It is “Tile”'s “Title”.

    • "subtitle"
      It is “Tile”'s “Subtitle”.

    • "image_url"
      It is “Thumbnail”'s URL.

    • "image_ratio"
      Such as: ‘16by9’, ‘4by3’, ‘1by1’ or ‘2by3’

    • “action_data”

      • “action_data” is data sent to an application when deep linking.
        Therefore, information should be contained in “action_data”, which is needed for deep linking into the specific page.
        The application receives the data and then can display the suitable page.

      • When deep linking, “action_data” is converted to ApplicationControlData as below.
        Therefore, the application can receive it by using tizen.application.getCurrentApplication().getRequestedAppControl method.
        For more detail, refer to it in chapter Get “action_data”.

        {
        	"key": "PAYLOAD",
        	"value": ["{\"values\": \"{\\\"videoIdx\\\": 1}\"}"]
        }
        

        action_data is contained under “PAYLOAD” key.
        For more ApplicationControlData, refer to Application API.

    • "is_playable"
      If this value is true, “Playable Icon” is shown.

    • "display_from"
      If you include it in JSON, “Tile” is shown from the specified time.

    • "display_until"
      If you include it in JSON, “Tile” is shown until the specified time.

    • "position"
      If you include it in JSON, “Tile” is in ascending order of position.

  • The following is a sample JSON.
    You can see this sample on the sampleJSON.
{
	"sections": [{
		"title": "Popular VOD",
		"tiles": [{
			"title": "Funny",
			"subtitle": "Birthday Party",
			"image_ratio": "16by9",
			"image_url": "https://developer.samsung.com/onlinedocs/tv/Preview/1.jpg",
			"action_data": "{\"videoIdx\": 1}",
			"is_playable": true
		}]
	},
	{
		"title": "VOD recommended",
		"tiles": [{
			"title": "Living",
			"image_ratio": "1by1",
			"image_url": "https://developer.samsung.com/onlinedocs/tv/Preview/2.jpg",
			"action_data": "{\"videoIdx\": 2}",
			"is_playable": true
		},
		{
			"title": "Cooking",
			"subtitle": "Season 1",
			"image_ratio": "16by9",
			"image_url": "https://developer.samsung.com/onlinedocs/tv/Preview/3.jpg",
			"action_data": "{\"pictureIdx\": 3}",
			"is_playable": false
		},
		{
			"title": "Party",
			"image_ratio": "16by9",
			"image_url": "https://developer.samsung.com/onlinedocs/tv/Preview/4.jpg",
			"action_data": "{\"pictureIdx\": 4}",
			"is_playable": false
		},
		{
			"title": "Animal",
			"image_ratio": "16by9",
			"image_url": "https://developer.samsung.com/onlinedocs/tv/Preview/5.jpg",
			"action_data": "{\"pictureIdx\": 5}",
			"is_playable": false
		}]
	}]
}
  • How to send different JSON base on TV information
    There are several parameters which an application can receive when “Preview” system requests JSON.
    These parameters have TV information, which are sent into HTTP headers.
    The application receives these information and send the suitable JSON to response.
    The following table describes the kind of HTTP headers.

    HTTP Header Description
    ACCEPT-LANGUAGE Standard HTTP header such as ‘en-US’
    X-SAMSUNG-COUNTRY ISO 3166-1 alpha2 format such as ‘US’
    X-SAMSUNG-APP-VERSION The application version. It maybe used to display different contents based on the application version.

Setting config.xml

Please declare the following metadata tag on “config.xml” for making “Preview”.

  • Connect your JSON URL (maybe on your server) at the following tag and declare it.

    <tizen:metadata key='http://samsung.com/tv/metadata/use.preview' value='endpoint_URL=http://yourServer/JSONfile.json'/>
    
  • As mentioned above, in case the application has already run in foreground or background, “action_data” should be sent to application without reloading.
    So, you should declare the following tag.

    <tizen:app-control>
    	<tizen:src name='index.html' reload='disable'/>
    	<tizen:operation name='http://samsung.com/appcontrol/operation/eden_resume'/>
    </tizen:app-control>
    

    The main HTML page of application should be connected in the name of tizen:src tag.
    If you don’t declare this tag, the application is reloaded although it has already run.
    For the application receives it, appcontrol event should be added. Plese refer to it in chapter Get “action_data”.

  • If you have plan to release the application on both 2015 and 2016 models, you should check Tizen platform version.
    The version of 2015 models is 2.3 and 2016 is 2.4.
    So, you should configure required_version to 2.3 and devel.api.verson to 2.4.

    <tizen:application ... required_version='2.3'/>
    <tizen:metadata key='http://samsung.com/tv/metadata/devel.api.version' value='2.4'/>
    

Getting action_data

  • When deep linking, as mentioned in caption Configure JSON file, the application should receive “action_data” by using tizen.application.getCurrentApplication().getRequestedAppControl method.
    You should call the following function on onload.
    (action_data is contained under “PAYLOAD” key.)

    function deepLink() {
    	var requestedAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
    	var appControlData;
    	var actionData;
    
    	var videoIdx;
    	var pictureIdx;
    
    	if (requestedAppControl) {
    		appControlData = requestedAppControl.appControl.data;
    		
    		for (var i = 0; i < appControlData.length; i++) {
    			if (appControlData[i].key == 'PAYLOAD') {
    				actionData = JSON.parse(appControlData[i].value[0]).values;
    
    				if(JSON.parse(actionData).videoIdx) {
    					videoIdx = JSON.parse(actionData).videoIdx
    
    					console.log(videoIdx);
    				}
    				else if(JSON.parse(actionData).pictureIdx) {
    					pictureIdx = JSON.parse(actionData).pictureIdx
    
    					console.log(pictureIdx);
    				}
    			}
    		}
    	} else {
    		console.log("no req app control");
    	}
    }
    

    For more detail code, refer to it in chapter Sample application.
    For more RequestedApplicationControl, refer to Application API.

  • As mentioned in chapter Set “config.xml”, the application can receive “action_data”, when the application has already run.
    You should add the following event on onload.
    (deepLink is function name, as mentioned above.)

    window.addEventListener('appcontrol', deepLink);
    

Using Background Service

It is required to implement Background service, you need to develop 1 foreground application and 1 background service.
Application is for your foreground work such as show main page or detail page.
Service application is for setting previewData to “PreviewDB” of TV platform side.
If you want more details about service application, please refer Service Application

Note

scheduling

  • While application sync, preview is managed by circular queue based on installed application list.
  • Background service ensures 5 minutes for each operation. If It is not terminated until 5 minutes, It would be killed by platform in force.
  • Background service is only running 1 process at once.

service excution

  • The service will only be executed for applicaitons pinned to the “Launcher”.
Important

Service Application Exit

  • After completed what your expected task, It is required to terminate background service using “tizen.application.getCurrentApplication().exit()”

Flow Chart

  • Launch “Background Service” from “Foreground Application”.

  • Prepare preview JSON data (Write local JSON data or HTTP request from your server)

  • Write JSON data directly to the “preview DB” using “setPreviewData” API on the “Background Service”.

  • “Preview” is shown.

  • If user clicks “Preview”, deep linking is occured.

  • “action_data” in JSON is sent to the “Foreground Application”.

  • In the “Foreground Application”, “action_data” is parsed. Finally, the detail page is shown.

Configuring JSON File

It is available to configure JSON File as above same way using “Server API”.
In "Background Service", It is available to use for preview as using local JSON data or JSON data from server.
If you want to configure JSON data with HTTP request, It is required to use HTTP request using Nodejs.

Important

Using “Background Service”, “expires” property in JSON data will be ignored. This property is only for “Server API”.

Setting PreviewData

If you want to get preview data from your server, you can use HTTP APIs provided by NodeJS. Making preview data locally is also available.
Depends on architecture of your application, personalization is available using sharing data between “Foreground Application” and “Backgroud Service” : for instance, account data, device information and so on. After getting from server or making preview data, use “setPreviewData” API to write it directly on “preview DB”. Please note that after called success callback of “setPreviewData” API, It is recommended to terminate service immediately.

// You can get preivew data from your server using HTTP networking or make local JSON data in the application.
// Depend on architecture of your application, personalization is available.
// Local JSON data example

// Dummy user data for customizing data
var user = {
	id : 'Rozanne',
	age : 27
}
var previewData = {
	"sections" : [ {
		"title" : user.id + "'s recommended",
		"tiles" : [ {
			"title" : "Funny",
			"subtitle" : user.age + "th Birthday Party",
			"image_ratio" : "16by9",
			"image_url" : "https://developer.samsung.com/onlinedocs/tv/Preview/1.jpg",
			"action_data" : "{\"videoIdx\": 1}",
			"is_playable" : true
		} ]
	}, {
		"title" : user.age + "'s choice",
		"tiles" : [ {
			"title" : user.id + "'s Living",
			"image_ratio" : "1by1",
			"image_url" : "https://developer.samsung.com/onlinedocs/tv/Preview/2.jpg",
			"action_data" : "{\"videoIdx\": 2}",
			"is_playable" : true
		}, {
			"title" : "Cooking",
			"subtitle" : "Season 1",
			"image_ratio" : "16by9",
			"image_url" : "https://developer.samsung.com/onlinedocs/tv/Preview/3.jpg",
			"action_data" : "{\"pictureIdx\": 3}",
			"is_playable" : false
		}, {
			"title" : user.id + "'s " + user.age + "th Party",
			"image_ratio" : "16by9",
			"image_url" : "https://developer.samsung.com/onlinedocs/tv/Preview/4.jpg",
			"action_data" : "{\"pictureIdx\": 4}",
			"is_playable" : false
		}, {
			"title" : user.id + "'s Animal",
			"image_ratio" : "16by9",
			"image_url" : "https://developer.samsung.com/onlinedocs/tv/Preview/5.jpg",
			"action_data" : "{\"pictureIdx\": 5}",
			"is_playable" : false
		} ]
	} ]
};

try {
	// setPreviewData with preview JSON data
	webapis.preview.setPreviewData(JSON.stringify(previewData),
		function(){
			console.log('setPreviewData SuccessCallback');
			// Should terminate service after setting preview data
			tizen.application.getCurrentApplication().exit();
		},
		function(e) {
			console.log('setPreviewData failed : ' + e.message);
		}
	);
} catch(e) {
	console.log('setPreviewData exception : ' + e.message);
}

Running Background Service

“Background Service” should be composed by NodeJS. “Background Service” is required to launch from “Foreground Application” using “launchAppControl” API.

foreground application side

// Launch Service
var serviceId = 'g3rAasdgsM.service';

tizen.application.launchAppControl(
	new tizen.ApplicationControl('http://tizen.org/appcontrol/operation/pick', null, 'imag/jpeg', null, 
	[new tizen.ApplicationControlData('caller',['ForegroundApp'])]), serviceId,
	function () {
		//success callback
		console.log('Launch success: ' + serviceId);
	},
	function (e) {
		console.log('Launch failed: ' + e.message);
	}
);

background service application side

After launching service application from foreground application, It will follow below life cycle.

  • Create “service/[service name].js” file in your application.
  • Service file must export the following methods.
  • onStart()
    Start point after the service runtime is set up.
// onStart Callback
module.exports.onStart = function()
{
	console.log("Start Callback");
}
  • onRequest()
    Called by the platform after being launched service application from foreground application. When the service application is launched for the first time, this method will be called. After you have done task you want, It is required to terminate service. This callback is recommended to be used for main logic such as HTTP networking, communication with foreground application or setPreviewData and so on.
//onRequest Callback
module.exports.onRequest = function()
{
	console.log("Request Callback");
	var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();

	if (reqAppControl && reqAppControl.appControl.operation == "http://tizen.org/appcontrol/operation/pick") {
		var data = reqAppControl.appControl.data;
		if (data[0].value[0] == 'ForegroundApp') {
			// ex) HTTP networking, setPreviewData API and so on
		}
	}
}
  • onExit()
    Called when the service exits.
//onExit Callback
module.exports.onExit = function()
{
	console.log("Exit Callback");
}

Setting config.xml

  • Add metadata to use preview.
<tizen:metadata key="http://samsung.com/tv/metadata/use.preview" value="bg_service"/>
  • Add the following to your config.xml under the to add service to the application.
<tizen:service id="O5ayZ5Ps6R.service">
	<tizen:content src="service/service.js"/>
	<tizen:name>service</tizen:name>
	<tizen:icon src="service/service_icon.png"/>
	<tizen:description>Service Application</tizen:description>
	<tizen:metadata key="meta-key" value="meta-value"/>
	<tizen:category name="http://tizen.org/category/service"/>
</tizen:service>

<tizen:service> id : combination of you application ID and the service name in the format of [application ID].[service name]
<tizen:content> src : point to the file containing the service code

  • As mentioned above, in case the application has already run in foreground or background, “action_data” should be sent to application without reloading.
    So, you should declare the following tag.
<tizen:app-control>
	<tizen:src name="index.html" reload="disable"/>
	<tizen:operation name="http://samsung.com/appcontrol/operation/eden_resume"/>
</tizen:app-control>

The main HTML page of application should be connected in the name of tizen:src tag.
If you don’t declare this tag, the application is reloaded although it has already run.
For the application receives it, appcontrol event should be added. Plese refer to it in chapter Get “action_data”.

  • If you have plan to release the application on both 2015 and 2016 models, you should check Tizen platform version.
    The version of 2015 models is 2.3 and 2016 is 2.4.
    So, you should configure required_version to 2.3 and devel.api.verson to 2.4.
<tizen:application ... required_version='2.3'/>
<tizen:metadata key="http://samsung.com/tv/metadata/devel.api.version" value="2.4"/>

Getting action_data

  • When deep linking, as mentioned in caption Configure JSON file, the application should receive “action_data” by using tizen.application.getCurrentApplication().getRequestedAppControl method.
    You should call the following function on onload.
    (action_data is contained under “PAYLOAD” key.)

    function deepLink() {
    	var requestedAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
    	var appControlData;
    	var actionData;
    
    	var videoIdx;
    	var pictureIdx;
    
    	if (requestedAppControl) {
    		appControlData = requestedAppControl.appControl.data;
    		
    		for (var i = 0; i < appControlData.length; i++) {
    			if (appControlData[i].key == 'PAYLOAD') {
    				actionData = JSON.parse(appControlData[i].value[0]).values;
    
    				if(JSON.parse(actionData).videoIdx) {
    					videoIdx = JSON.parse(actionData).videoIdx
    
    					console.log(videoIdx);
    				}
    				else if(JSON.parse(actionData).pictureIdx) {
    					pictureIdx = JSON.parse(actionData).pictureIdx
    
    					console.log(pictureIdx);
    				}
    			}
    		}
    	} else {
    		console.log("no req app control");
    	}
    }
    

    For more detail code, refer to it in chapter Sample application.
    For more RequestedApplicationControl, refer to Application API.

  • As mentioned in chapter Set “config.xml”, the application can receive “action_data”, when the application has already run.
    You should add the following event on onload.
    (deepLink is function name, as mentioned above.)

    window.addEventListener('appcontrol', deepLink);
    

Sharing data between Foreground App and Background Service

You can use Message Port API to share data between foreground application and background service. For instance sharing account information entered by the user in the foreground application with the background service querying for personalized recommendations.

  • Message Port API
    for more details, refer this

Sample Application

Using Server API

Using Background Service

Reference Videos

The following video is for better understanding.