This document assumes you already have a cast-enabled mobile app and a working Tizen TV app. It walks through and compares the steps needed to incorporate Smart View SDK support into a standard Chromecast integration that uses a custom receiver app. This example is based on Android but the same principles can be easily be extended to cover the iOS or Javascript APIs.
// Get an instance of Search
Search search = Service.search(getContext());
// Add a listener for the service found event
search.setOnServiceFoundListener(
new OnServiceFoundListener() {
@Override
public void onFound(Service service) {
// Add service to a displayed list
//where your user can select one.
}
}
);
// Add a listener for the service lost event
search.setOnServiceLostListener(
new OnServiceLostListener() {
@Override
public void onLost(Service service) {
// Remove this service
//from the displayed list.
}
}
);
// Start the discovery process
search.start();
// Do something while we wait for services to be discovered.
...
// Stop the discovery process after some amount of time,
search.stop();
Launch
NoteSender app launches the receiver app.
And receiver app could be installed TV Apps.
The general mobile workflow is:
Step
Google Cast
Smart View SDK
1
Sender app creates a GoogleApiClient GoogleApiClient.Builder
service instance is returned OnFound()
2
Sender app connects the GoogleApiClient GoogleApiClient.connect
service.createApplication(appId, channelId) Create an application reference to your tv app by app id, and channel id
3
GoogleApiClient.ConnectionCallbacks.onConnected
application.connect() / application.disconnect() Connect to the tv application Disconnect from the tv application
4
Sender app launches the receiver app: Cast.CastApi.launchApplication
Listen for the connect / disconnect event onConnect, onDisConnect
Example GoogleCast Android API Usage
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
mApiClient.connect();
private class ConnectionCallbacks implements
GoogleApiClient.ConnectionCallbacks {
@Override
public void onConnected(Bundle connectionHint) {
if (mWaitingForReconnect) {
Cast.CastApi.launchApplication(mApiClient, "YOUR_APPLICATION_ID", false)
.setResultCallback(
new ResultCallback() {
@Override
public void onResult(Cast.ApplicationConnectionResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata =
result.getApplicationMetadata();
String sessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
...
} else {
teardown();
}
}
});
}
Example SmartView SDK Android API Usage
// Tizen WebApp
String url = "YOUR_APPLICATION_ID";
// Example channel id
String channelId = "com.samsung.multiscreen.helloworld";
// Get an instance of Application.
Application application = service.createApplication(url, channelId);
// Listen for the connect event
application.setOnConnectListener(new OnConnectListener() {
@Override
public void onConnect(Client client) {
Log.d(LOGTAG, "Application.onConnect():" + client.toString());
}
});
// Connect and launch the application.
// When you connect to a service, the specified application will
// be launched automatically.
application.connect(new Result() {
@Override
public void onSuccess(Client client) {
// The application is launched, and is ready to accept messages.
}
@Override
public void onError(Error error) {
}
);
Communicate
NoteSender sends a message to the receiver over the communication channel.
and you can send messages to/from any or all clients connected including the TV.
furthermore you can receive incoming messages from another device.
The general mobile workflow is:
Step
Google Cast
Smart View SDK
1
Sender app creates a communication channel Cast.CastApi.setMessageReceivedCallbacks
Sender sends a message to the receiver application.publish
2
Sender sends a message to the receiver over the communication channel Cast.CastApi.sendMessage*
Sender receive a message onMessage
3
Sender receive a message onMessageReceived
Example GoogleCast Android API Usage
/*************
1. Send
**************/
private void sendMessage(String message) {
if (mApiClient != null && mHelloWorldChannel != null) {
try {
Cast.CastApi.sendMessage(mApiClient
,mHelloWorldChannel.getNamespace()
,message)
.setResultCallback(
new ResultCallback() {
@Override
public void onResult(Status result) {
if (!result.isSuccess()) {
Log.e(TAG, "Sending message failed");
}
}
});
} catch (Exception e) {
Log.e(TAG, "Exception while sending message", e);
}
}
}
/*************
2. Receive
**************/
public String getNamespace() {
return "urn:x-cast:com.example.custom";
}
@Override
public void onMessageReceived(CastDevice castDevice, String namespace, String message) {
Log.d(TAG, "onMessageReceived: " + message);
}
}
Cast.CastApi.launchApplication(mApiClient,"YOUR_APPLICATION_ID" , false).setResultCallback(
new ResultCallback() {
@Override
public void onResult(Cast.ApplicationConnectionResult result){
Status status = result.getStatus();
if (status.isSuccess()) {
mHelloWorldChannel = new HelloWorldChannel();
try {
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,
mHelloWorldChannel.getNamespace(),
mHelloWorldChannel);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel", e);
}
}
}
});
Example SmartView SDK Android API Usage
/*************
1. Send
**************/
// Note: The TV application is designated as the "HOST"
String event = "say";
String messageData = "Hello World!";
// Send a message to the TV application only, by default.
application.publish(event, messageData);
// Send a message to the TV application, explicitly.
application.publish(event, messageData, Message.TARGET_HOST);
// Send a "broadcast" message to all clients EXCEPT yourself.
application.publish(event, messageData, Message.TARGET_BROADCAST);
// Send a message to all clients INCLUDING yourself
application.publish(event, messageData, Message.TARGET_ALL);
// Send a message to a specific client
String clientId = "123467"; // Assuming that this is a valid id
Client client = channel.getClients().get(clientId);
application.publish(event, messageData, client);
// Send a message to a list of clients
List clients = ...
application.publish(event, messageData, clients);
// Send a binary message to the TV application only, by default.
byte[] payload = {0x00, 0x01, 0x02, 0x03};
application.publish(event, messageData, payload);
/*************
2. Receive
**************/
// The event that this client is interested in
// receiving published messages.
String event = "say";
// Listen for a message by event
application.addOnMessageListener(event, new OnMessageListener() {
@Override
public void onMessage(Message message) {
Log.d(LOGTAG, "message: " + message.toString());
// Got a message with some data or a binary payload.
}
});
Receiver Application
The general mobile workflow is:
Step
Google Cast
Smart View SDK
1
3 types of receiver app: Default, Styled, Custom
Custom type Receiver App
2
Get castReceiverManager instance
Get a reference to the "local" service window.msf.local {}
3
Override/provide any event listeners on the CastReceiverManager.
Connect to a communication "channel" service.channel('CHANNEL_NAME');
4
Custom protocol extensions (namespaces), call getCastMessageBus for the namespaces to be used.
Add Event Listeners
5
Call start on the CastReceiverManager to indicate the receiver application is ready to receive messages
Example GoogleCast Android API Usage
window.onload = function() {
window.castReceiverManager
= cast.receiver.CastReceiverManager.getInstance();
console.log('Starting Receiver Manager');
// handler for the 'ready' event
castReceiverManager.onReady = function(event) {
};
// handler for 'senderconnected' event
castReceiverManager.onSenderConnected = function(event) {
};
// handler for 'senderdisconnected' event
castReceiverManager.onSenderDisconnected = function(event) {
}
};
// create a CastMessageBus to handle messages
// for a custom namespace
window.messageBus =
window.castReceiverManager.getCastMessageBus(
'urn:x-cast:com.google.cast.sample.helloworld');
// handler for the CastMessageBus message event
window.messageBus.onMessage = function(event) {
// display the message from the sender
displayText(event.data);
// inform all senders on the CastMessageBus
// of the incoming message event
// sender message listener will be invoked
window.messageBus.send(event.senderId, event.data);
}
// initialize the CastReceiverManager
// with an application status message
window.castReceiverManager.start
({statusText: "Application is starting"});
};
You have two options for multimedia player in Tizen application.
Use HTML5 `````` tag. It doesn’t support DRMs and streaming engines like DASH, HAS, HLS and SmoothStreaming.
Use avplay API or Samsung TV product API. It supports DRMs and streaming engines like DASH, HAS, HLS and SmoothStreaming.
If your application has simple functionalities and plays multimedia without DRM and streaming engine, using HTML5 `````` tag may be convenience. and if your application uses DRM or streaming engine, we recommend using avplay API.
Set listener event by webapis.avplay.setListener()
3
Creating a Protocol object
Call webapis.avplay.prepare()
4
load the media and start at a specific position (typically 0) window.player.load(protocol, initStart);
Set media size by webapis.avplay.setDisplayRect()
5
Call webapis.avplay.play()
Example GoogleCast Android API Usage
var mediaElement = document.getElementById('vid');
// Create the media manager. This will handle all media messages by default.
window.mediaManager = new cast.receiver.MediaManager(mediaElement);
if (event.data['media'] && event.data['media']['contentId']) {
console.log('Starting media application');
var url = event.data['media']['contentId'];
// Create the Host - much of your interaction with the library uses the Host and
// methods you provide to it.
window.host = new cast.player.api.Host(
{'mediaElement':mediaElement, 'url':url});
var ext = url.substring(url.lastIndexOf('.'), url.length);
var initStart = event.data['media']['currentTime'] || 0;
var autoplay = event.data['autoplay'] || true;
var protocol = null;
mediaElement.autoplay = autoplay; // Make sure autoplay get's set
if (url.lastIndexOf('.m3u8') >= 0) {
// HTTP Live Streaming
protocol = cast.player.api.CreateHlsStreamingProtocol(host);
} else if (url.lastIndexOf('.mpd') >= 0) {
// MPEG-DASH
protocol = cast.player.api.CreateDashStreamingProtocol(host);
} else if (url.indexOf('.ism/') >= 0) {
// Smooth Streaming
protocol = cast.player.api.CreateSmoothStreamingProtocol(host);
}
// How to override a method in Host. I know that it's safe to just provide this
// method.
host.onError = function(errorCode) {
console.log("Fatal Error - " + errorCode);
if (window.player) {
window.player.unload();
window.player = null;
}
};
if (protocol !== null) {
console.log("Starting Media Player Library");
window.player = new cast.player.api.Player(host);
window.player.load(protocol, initStart);
}
else {
window.defaultOnLoad(event); // do the default process
}
window.player = null;
console.log('Application is ready, starting system');
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
castReceiverManager.start();
Example SmartView SDK Android API Usage
var config = {
url: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
player: document.getElementById('av-player'),
/*Smooth Streaming examples*/
// 'http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest',
// url: 'http://playready.directtaps.net/smoothstreaming/TTLSS720VC1/To_The_Limit_720.ism/Manifest'
};
if (!url) {
url = config.url;
}
log('videoPlayer open: ' + url);
try {
webapis.avplay.open(url);
webapis.avplay.setDisplayRect(
x,
y,
width,
height
);
webapis.avplay.setListener(listener);
} catch (e) {
log(e);
}
//set bitrates according to the values in your stream manifest
// this.setBitrate(477000, 2056000, 2056000, 688000);
webapis.avplay.prepare();
webapis.avplay.play();
// pause
webapis.avplay.pause();
// stop
webapis.avplay.stop();
// close :To destroy the avplay object
webapis.avplay.close();
// Backward
webapis.avplay.jumpBackward(time);
// Forward
webapis.avplay.jumpForward(time);
// Time
var duration = webapis.avplay.getDuration();
var currentTime = webapis.avplay.getCurrentTime();
Integrating Smart View SDK and Google Cast
Example Android API Usage
/****************************************
1. Discover
****************************************/
//Smart View SDK Search
mSearch = Service.search(mContext);
mSearch.start();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
/****************************************
2. add Listener to discover device
*****************************************/
//Smart View SDK
mSearch.setOnServiceFoundListener(
new Search.OnServiceFoundListener() {
@Override
public void onFound(Service service) {
Log.d(TAG, "Search.onFound() service : " + service.toString());
if(!mDeviceList.contains(service)) {
mDeviceList.add(service);
mTVListAdapter.add(service);
mTVListAdapter.notifyDataSetChanged();
}
}
}
);
mSearch.setOnServiceLostListener(
new Search.OnServiceLostListener() {
@Override
public void onLost(Service service) {
Log.d(TAG, "Search.onLost() service : " + service.toString());
mDeviceList.remove(service);
mTVListAdapter.remove(service);
mTVListAdapter.notifyDataSetChanged();
}
}
);
/**
* For intergrate Google Cast Device discover
* Callback for MediaRouter events
*/
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
CastDevice castDevice = CastDevice.getFromBundle(route.getExtras());
Log.d(TAG, "onRouteAdded CastDevice = " + route.toString());
if(!mDeviceList.contains(castDevice)) {
mDeviceList.add(castDevice);
mTVListAdapter.add(castDevice);
mTVListAdapter.notifyDataSetChanged();
}
}
@Override
public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
CastDevice castDevice = CastDevice.getFromBundle(route.getExtras());
Log.d(TAG, "onRouteChanged CastDevice = " + route.toString());
if(!mDeviceList.contains(castDevice)) {
mDeviceList.add(castDevice);
mTVListAdapter.add(castDevice);
mTVListAdapter.notifyDataSetChanged();
}
}
@Override
public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
Log.d(TAG, "onRouteRemoved");
CastDevice castDevice = CastDevice.getFromBundle(route.getExtras());
mDeviceList.add(castDevice);
mTVListAdapter.remove(castDevice);
mTVListAdapter.notifyDataSetChanged();
}
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteSelected -- not use");
Log.d(TAG, "onRouteSelected");
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteUnselected ---not use");
}
}
/****************************************
3. Discover stop
****************************************/
// Smart View SDK
mSearch.stop();
// Google cast. End media router discovery
mMediaRouter.removeCallback(mMediaRouterCallback);
/****************************************
4. Launch :
How to get MSF "Service" and google cast "CastDevice"
****************************************/
String cName = mTVListAdapter.getItem(which).getClass().getName();
if (Service.class.getName().equals(cName)) {
// Launch Smart View SDK app
}else if (CastDevice.class.getName().equals(cName)) {
// Launch Google Cast app
}
Sample Application
Here are two basic applications.
It's very similar and easy to understand how works with each SDK
This is a very simple application that demonstrates the basics of working with the SDK.
It will allow you to understand and visualize how the core features work.
This includes the "discovery" process, launching a tv app, and sending/receiving simple messages.
This application is the best one to start with if you are new to the SDK.
There are Android mobile versions available and the source for the TV app is also included.
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.