SlideShare ist ein Scribd-Unternehmen logo
1 von 106
Downloaden Sie, um offline zu lesen
Seu App na TV: 
Desenvolvimento 
para ChromeCast 
Ivan de Aguirre 
! 
ivan.aguirre@gmail.com 
! 
Twitter: IvAguirre 
! 
G+: plus.google.com/+IvanAguirreBr
Sender App:
Sender App: 
Android
Sender App: 
Android 
iOS
Sender App: 
Android 
iOS 
Chrome App
Sender App: 
Android 
iOS 
Chrome App 
Receiver App:
Sender App: 
Android 
iOS 
Chrome App 
Receiver App: 
HTML 5
Sender App: 
Android 
iOS 
Chrome App 
Receiver App: 
HTML 5 
<video>
Sender App: 
Android 
iOS 
Chrome App 
Receiver App: 
HTML 5 
<video> 
Registro
Sender App: 
Android 
iOS 
Chrome App 
Receiver App: 
HTML 5 
<video> 
Registro 
Application ID = URL
Workflow em detalhes
Workflow em detalhes 
• Descoberta do Chromecast.
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID.
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID. 
• Envio do Application ID ao Chromecast.
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID. 
• Envio do Application ID ao Chromecast. 
• Chromecast acessa a URL do Application ID: Receiver App no ar!!
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID. 
• Envio do Application ID ao Chromecast. 
• Chromecast acessa a URL do Application ID: Receiver App no ar!! 
• Sender envia a URL para o vídeo (media channel) e/ou…
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID. 
• Envio do Application ID ao Chromecast. 
• Chromecast acessa a URL do Application ID: Receiver App no ar!! 
• Sender envia a URL para o vídeo (media channel) e/ou… 
• Envia texto (custom channel).
Workflow em detalhes 
• Descoberta do Chromecast. 
• (Re)Conexão com o Chromecast: sessionID. 
• Envio do Application ID ao Chromecast. 
• Chromecast acessa a URL do Application ID: Receiver App no ar!! 
• Sender envia a URL para o vídeo (media channel) e/ou… 
• Envia texto (custom channel). 
• Callbacks, callbacks, callbacks, callbacks…
Por dentro do Chromecast
Por dentro do Chromecast 
• Chrome Browser.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript. 
• Limitações de memória e CPU.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript. 
• Limitações de memória e CPU. 
• Sem WebGL ou Chrome Extensions.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript. 
• Limitações de memória e CPU. 
• Sem WebGL ou Chrome Extensions. 
• Nada de Tabs, janelas, popups ou inputs.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript. 
• Limitações de memória e CPU. 
• Sem WebGL ou Chrome Extensions. 
• Nada de Tabs, janelas, popups ou inputs. 
• Suporte à WebAudio API.
Por dentro do Chromecast 
• Chrome Browser. 
• HTML5, CSS 3, JavaScript. 
• Limitações de memória e CPU. 
• Sem WebGL ou Chrome Extensions. 
• Nada de Tabs, janelas, popups ou inputs. 
• Suporte à WebAudio API. 
• Uma tag <video> ativa por vez.
developers.google.com/cast 
! 
developers.google.com/cast/ 
docs/ux_guidelines 
! 
developers.google.com/cast/ 
docs/design_checklist
Sender 
com.android.support:appcompat-v7 
! 
com.android.support:mediarouter-v7 
! 
com.google.android.gms:play-services
Sender 
GoogleApiClient.ConnectionCallbacks 
GoogleApiClient.OnConnectionFailedListener 
MediaRouter.Callback 
Cast.Listener 
ResultCallback<Cast.ApplicationConnectionResult> 
RemoteMediaPlayer.OnStatusUpdatedListener 
RemoteMediaPlayer.OnMetadataUpdatedListener 
ResultCallback<RemoteMediaPlayer.MediaChannelResult>
Sender 
GoogleApiClient.ConnectionCallbacks 
GoogleApiClient.OnConnectionFailedListener 
MediaRouter.Callback 
Cast.Listener 
ResultCallback<Cast.ApplicationConnectionResult> 
RemoteMediaPlayer.OnStatusUpdatedListener 
RemoteMediaPlayer.OnMetadataUpdatedListener 
ResultCallback<RemoteMediaPlayer.MediaChannelResult>
Sender 
github.com/googlecast/ 
CastCompanionLibrary-android
Sender + CastCompanionLibrary 
public 
class 
MyApplication 
extends 
Application 
{ 
private 
static 
VideoCastManager 
mCastMgr; 
public 
static 
VideoCastManager 
getVideoCastManager(Context 
ctx) 
{ 
if 
(null 
== 
mCastMgr) 
{ 
! 
mCastMgr 
= 
VideoCastManager.initialize(ctx, 
"XYZ1234", 
null, 
/* 
activity 
com 
player 
*/ 
null 
/* 
namespace 
*/); 
mCastMgr.enableFeatures(… 
! 
} 
mCastMgr.setContext(ctx); 
return 
mCastMgr; 
} 
}
Sender + CastCompanionLibrary 
public 
class 
MainActivity 
extends 
ActionBarActivity 
{ 
private 
VideoCastManager 
mVideoCastManager; 
@Override 
protected 
void 
onCreate(Bundle 
savedInstanceState) 
{ 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
BaseCastManager.checkGooglePlayServices(this); 
mVideoCastManager 
= 
MyApplication.getVideoCastManager( 
this); 
mVideoCastManager.reconnectSessionIfPossible(this, 
true, 
5 
/*sec*/); 
} 
}
Sender + CastCompanionLibrary 
public 
boolean 
onCreateOptionsMenu(Menu 
menu) 
{ 
super.onCreateOptionsMenu(menu); 
! 
getMenuInflater().inflate(R.menu.main, 
menu); 
! 
mVideoCastManager.addMediaRouterButton(menu, 
R.id.media_route_menu_item); 
! 
return 
true; 
}
Sender + CastCompanionLibrary 
MediaMetadata 
mediaMetadata 
= 
new 
MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); 
mediaMetadata.putString(MediaMetadata.KEY_TITLE, 
"Title: 
Chromecast 
na 
QCON 
RJ 
2014"); 
mediaMetadata.putString(MediaMetadata.KEY_SUBTITLE, 
""); 
mediaMetadata.putString(MediaMetadata.KEY_STUDIO, 
"Ivan 
de 
Aguirre 
Productions"); 
MediaInfo 
mediaInfo 
= 
new 
MediaInfo.Builder( 
"https://d2k4ls0ga9ks2.cloudfront.net/VID_20140727_225510282.mp4") 
.setContentType("video/mp4") 
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) 
.setMetadata(mediaMetadata) 
.build(); 
mVideoCastManager.startCastControllerActivity(this, 
mediaInfo, 
0, 
true);
Receiver
Receiver 
• Default Receiver.
Receiver 
• Default Receiver. 
• Styled Receiver.
Receiver 
• Default Receiver. 
• Styled Receiver. 
• Custom Receiver.
Custom Receiver Mínimo 
<html> 
<head> 
<title>Example 
minimum 
receiver</title> 
<script 
src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></ 
script> 
</head> 
<body> 
<video 
id='media'/> 
<script> 
... 
</script> 
</body> 
</html>
Custom Receiver Mínimo 
<script> 
window.onload 
= 
function() 
{ 
window.mediaElement=document.getElementById('media'); 
! 
window.mediaManager 
= 
new 
cast.receiver.MediaManager( 
window.mediaElement); 
! 
window.castReceiverManager 
= 
cast.receiver 
.CastReceiverManager.getInstance(); 
! 
window.castReceiverManager.start(); 
} 
</script>
Exemplo 1
Exemplo 1 
• Custom Receiver para exibir propaganda e notificações no 
telefone.
Exemplo 1 
• Custom Receiver para exibir propaganda e notificações no 
telefone. 
• Envia URL do vídeo pelo Media Channel.
Exemplo 1 
• Custom Receiver para exibir propaganda e notificações no 
telefone. 
• Envia URL do vídeo pelo Media Channel. 
• Envia texto pelo Custom Channel com as notificações.
Exemplo 1 
• Custom Receiver para exibir propaganda e notificações no 
telefone. 
• Envia URL do vídeo pelo Media Channel. 
• Envia texto pelo Custom Channel com as notificações. 
• No Receiver exibe propagandas.
Exemplo 1 - Sender 
public 
class 
MyApplication 
extends 
Application 
{ 
private 
static 
VideoCastManager 
mCastMgr; 
public 
static 
VideoCastManager 
getVideoCastManager(Context 
ctx) 
{ 
if 
(null 
== 
mCastMgr) 
{ 
mCastMgr 
= 
VideoCastManager.initialize(ctx, 
"XYZ1234", 
"urn:x-­‐cast:org.gcastsamples.castnotifications"); 
// 
configurar 
opções... 
} 
! 
mCastMgr.setContext(ctx); 
return 
mCastMgr; 
} 
}
Exemplo 1 - Sender 
public 
class 
MyNotificationListenerService 
extends 
NotificationListenerService 
{ 
@Override 
public 
void 
onNotificationPosted(StatusBarNotification 
statusBarNotification) 
{ 
String 
msg 
= 
String.valueOf( 
statusBarNotification.getNotification().tickerText); 
! 
try 
{ 
! 
MyApplication.getVideoCastManager(getApplicationContext()) 
.sendDataMessage(msg); 
! 
} 
catch 
(TransientNetworkDisconnectionException 
e) 
{ 
Log.e("NotificationListenerService", 
"Can't 
send 
message", 
e); 
} 
catch 
(NoConnectionException 
e) 
{ 
Log.e("NotificationListenerService", 
"Can't 
send 
message", 
e); 
} 
} 
}
Exemplo 1 - Receiver 
<div 
id="notification_banner" 
class="alert 
alert-­‐info" 
role="alert"> 
<h4>New 
Notification 
from 
your 
phone!!</h4> 
<p 
id="notification_text">Test!!!</p> 
</div> 
! 
<div 
id="ad_banner" 
class="alert 
alert-­‐warning" 
role="alert"> 
<h4 
id="ad_text">New 
Notification 
from 
your 
phone!!</h4> 
</div> 
! 
<video 
id="media"/>
Exemplo 1 - Receiver 
window.mediaElement 
= 
document.getElementById('media'); 
window.mediaElement.addEventListener('playing', 
function(event) 
{ 
advertising.start(); 
}); 
! 
window.mediaManager 
= 
new 
cast.receiver.MediaManager(window.mediaElement); 
window.castReceiverManager 
= 
cast.receiver.CastReceiverManager.getInstance(); 
! 
window.castReceiverManager.onSenderDisconnected 
= 
function(event) 
{ 
if 
(window.castReceiverManager.getSenders().length 
== 
0 
&& 
event.reason 
== 
cast.receiver.system.DisconnectReason.REQUESTED_BY_SENDER) 
{ 
advertising.stop(); 
window.close(); 
}
Exemplo 1 - Receiver 
var 
nms 
= 
'urn:x-­‐cast:org.gcastsamples.castnotifications'; 
var 
customMessageBus 
= 
window.castReceiverManager 
.getCastMessageBus(nms); 
customMessageBus.onMessage 
= 
function(event) 
{ 
showNotification(event.data); 
} 
window.castReceiverManager.start();
Exemplo 2
Exemplo 2 
• Custom Receiver para exibir um gráfico.
Exemplo 2 
• Custom Receiver para exibir um gráfico. 
• www.flotcharts.org
Exemplo 2 
• Custom Receiver para exibir um gráfico. 
• www.flotcharts.org 
• A página do Custom Receiver quando acessada pelo Chromecast 
é um Receiver.
Exemplo 2 
• Custom Receiver para exibir um gráfico. 
• www.flotcharts.org 
• A página do Custom Receiver quando acessada pelo Chromecast 
é um Receiver. 
• A página do Custom Receiver quando acessada pelo Browser é 
uma aplicação Web.
Exemplo 2
Exemplo 2 - Sender 
public 
class 
MyApplication 
extends 
Application 
{ 
! 
private 
static 
DataCastManager 
mCastMgr; 
public 
static 
final 
String 
NAME_SPACE 
= 
"urn:x-­‐cast:org.gcastsamples.plotandcast"; 
public 
static 
DataCastManager 
getDataCastManager(Context 
ctx) 
{ 
if 
(null 
== 
mCastMgr) 
{ 
mCastMgr 
= 
DataCastManager.initialize(ctx,"XYZ123", 
NAME_SPACE); 
} 
! 
mCastMgr.setContext(ctx); 
return 
mCastMgr; 
} 
}
Exemplo 2 - Sender 
String 
json 
= 
getData(); 
! 
mDataCastManager.sendDataMessage( 
json, 
MyApplication.NAME_SPACE);
Exemplo 2 - Receiver 
<body> 
<form 
id="plot_inputs"> 
… 
</form> 
<div 
id="content"> 
<div 
class="chart-­‐container"> 
<div 
id="placeholder" 
class="chart-­‐placeholder"></div> 
</div> 
</div> 
</body>
Exemplo 2 - Receiver 
if 
(navigator.userAgent.indexOf('CrKey') 
>= 
0) 
{ 
! 
$('#plot_inputs').hide(); 
// 
form 
inputs 
$('.chart-­‐container').addClass('chart-­‐container-­‐for-­‐tv'); 
! 
startChromeCastMode(); 
! 
} 
else 
{ 
! 
startBrowserMode(); 
! 
}
Exemplo 2 - Receiver 
function 
startChromeCastMode() 
{ 
window.onload 
= 
function() 
{ 
window.castReceiverManager 
= 
cast.receiver.CastReceiverManager.getInstance(); 
var 
nms='urn:x-­‐cast:org.gcastsamples.plotandcast'; 
var 
customMessageBus 
= 
window.castReceiverManager.getCastMessageBus(nms); 
customMessageBus.onMessage 
= 
function(event) 
{ 
var 
json 
= 
$.parseJSON(event.data);; 
plot(json); 
} 
window.castReceiverManager.start(); 
} 
}
Mirror e Presentation
Mirror e Presentation 
• Transmissão de Tela (Mirroring).
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+:
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+: 
• Em modo Mirror renderizar um Layout na TV (não há 
receiver).
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+: 
• Em modo Mirror renderizar um Layout na TV (não há 
receiver). 
• Wireless Display.
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+: 
• Em modo Mirror renderizar um Layout na TV (não há 
receiver). 
• Wireless Display. 
• Suporta Miracast.
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+: 
• Em modo Mirror renderizar um Layout na TV (não há 
receiver). 
• Wireless Display. 
• Suporta Miracast. 
• E Chromecast :)
Mirror e Presentation 
• Transmissão de Tela (Mirroring). 
• Presentation API: API Level 17, Android 4.2+: 
• Em modo Mirror renderizar um Layout na TV (não há 
receiver). 
• Wireless Display. 
• Suporta Miracast. 
• E Chromecast :) 
• Plugin do Chromecast para Chrome: espelha aba e tela.
Mirror e Presentation
Mirror e Presentation
Exemplo 3 - Mirror e Presentation
Exemplo 3 - Mirror e Presentation 
•Aplicação insere elementos em 
uma lista.
Exemplo 3 - Mirror e Presentation 
•Aplicação insere elementos em 
uma lista. 
• A lista é renderizada e 
manipulada na TV.
Exemplo 3 - Mirror e Presentation 
•Aplicação insere elementos em 
uma lista. 
• A lista é renderizada e 
manipulada na TV. 
•Não é casting!!
Exemplo 3 - Mirror e Presentation 
public 
class 
ListPresentation 
extends 
Presentation 
{ 
private 
RecyclerView 
mRecyclerView; 
private 
RecyclerView.LayoutManager 
mLayoutManager; 
private 
MyAdapter 
mAdapter; 
public 
ListPresentation(Context 
context, 
Display 
display) 
{ 
super(context, 
display); 
} 
@Override 
protected 
void 
onCreate(Bundle 
savedInstanceState) 
{ 
super.onCreate(savedInstanceState); 
Context 
ctx 
= 
getContext(); 
Resources 
r 
= 
ctx.getResources(); 
setContentView(R.layout.presentation); 
mRecyclerView 
= 
(RecyclerView) 
findViewById(R.id.list); 
mLayoutManager 
= 
new 
LinearLayoutManager(ctx); 
mRecyclerView.setLayoutManager(mLayoutManager); 
mRecyclerView.setItemAnimator(new 
DefaultItemAnimator()); 
mAdapter 
= 
new 
MyAdapter(); 
mRecyclerView.setAdapter(mAdapter); 
} 
...
MediaRouter 
mMediaRouter 
= 
(MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); 
MediaRouter.RouteInfo 
route 
= 
mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); 
Display 
presentationDisplay 
= 
route 
!= 
null 
? 
route.getPresentationDisplay() 
: 
null; 
if 
(mPresentation 
!= 
null 
&& 
mPresentation.getDisplay() 
!= 
presentationDisplay) 
{ 
mPresentation.dismiss(); 
mPresentation 
= 
null; 
} 
if 
(mPresentation 
== 
null 
&& 
presentationDisplay 
!= 
null) 
{ 
mPresentation 
= 
new 
ListPresentation(this, 
presentationDisplay); 
mPresentation.setOnDismissListener(mOnDismissListener); 
try 
{ 
mPresentation.show(); 
} 
catch 
(WindowManager.InvalidDisplayException 
ex) 
{ 
Log.w(TAG, 
"Display 
was 
removed 
in 
the 
meantime.", 
ex); 
mPresentation 
= 
null; 
} 
} 
Exemplo 3 - Mirror e Presentation
MediaRouter 
mMediaRouter 
= 
(MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); 
MediaRouter.RouteInfo 
route 
= 
mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); 
Display 
presentationDisplay 
= 
route 
!= 
null 
? 
route.getPresentationDisplay() 
: 
null; 
if 
(mPresentation 
!= 
null 
&& 
mPresentation.getDisplay() 
!= 
presentationDisplay) 
{ 
mPresentation.dismiss(); 
mPresentation 
= 
null; 
} 
if 
(mPresentation 
== 
null 
&& 
presentationDisplay 
!= 
null) 
{ 
mPresentation 
= 
new 
ListPresentation(this, 
presentationDisplay); 
mPresentation.setOnDismissListener(mOnDismissListener); 
try 
{ 
mPresentation.show(); 
} 
catch 
(WindowManager.InvalidDisplayException 
ex) 
{ 
Log.w(TAG, 
"Display 
was 
removed 
in 
the 
meantime.", 
ex); 
mPresentation 
= 
null; 
} 
} 
Exemplo 3 - Mirror e Presentation 
android.media.MediaRouter 
não é app compact!!
MediaRouter 
mMediaRouter 
ROUTE_TYPE_LIVE_AUDIO 
= 
(MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); 
MediaRouter.RouteInfo 
route 
= 
mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); 
Display 
presentationDisplay 
= 
route 
!= 
null 
? 
route.getPresentationDisplay() 
: 
null; 
if 
(mPresentation 
!= 
null 
&& 
mPresentation.getDisplay() 
!= 
presentationDisplay) 
{ 
mPresentation.dismiss(); 
mPresentation 
= 
null; 
} 
if 
(mPresentation 
== 
null 
&& 
presentationDisplay 
!= 
null) 
{ 
mPresentation 
= 
new 
ListPresentation(this, 
presentationDisplay); 
mPresentation.setOnDismissListener(mOnDismissListener); 
try 
{ 
mPresentation.show(); 
} 
catch 
(WindowManager.InvalidDisplayException 
ex) 
{ 
Log.w(TAG, 
"Display 
was 
removed 
in 
the 
meantime.", 
ex); 
mPresentation 
= 
null; 
} 
} 
Exemplo 3 - Mirror e Presentation 
android.media.MediaRouter 
não é app compact!!
Chrome Sender
Chrome Sender
Chrome Sender
Developer Tools: <chromecast ip>:9222
Developer Tools: <chromecast ip>:9222
Developer Tools: <chromecast ip>:9222 
• window.location.reload(true);
Developer Tools: <chromecast ip>:9222 
• window.location.reload(true); 
• window.location.replace('http://myhost.com/receiver.html');
FAQ
FAQ 
• Sender/Receiver: HTTPS.
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção.
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. 
• Múltiplas conexões ao receiver.
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. 
• Múltiplas conexões ao receiver. 
• Segurança: é preciso implementar os mecanismos.
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. 
• Múltiplas conexões ao receiver. 
• Segurança: é preciso implementar os mecanismos. 
• Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth 
Streaming, DRM, etc..
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. 
• Múltiplas conexões ao receiver. 
• Segurança: é preciso implementar os mecanismos. 
• Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth 
Streaming, DRM, etc.. 
• CORS.
FAQ 
• Sender/Receiver: HTTPS. 
• URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. 
• Múltiplas conexões ao receiver. 
• Segurança: é preciso implementar os mecanismos. 
• Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth 
Streaming, DRM, etc.. 
• CORS. 
• Não esqueçam do iOS :)
Futuro
Futuro 
• Google TV?
Futuro 
• Google TV? 
• Chrome OS: integração no Google Drive na build 
de desenvolvimento.
Futuro 
• Google TV? 
• Chrome OS: integração no Google Drive na build 
de desenvolvimento. 
• Conexão fora da mesma rede Wifi.
Referências 
developers.google.com/cast 
cast.google.com/publish 
github.com/googlecast 
code.google.com/p/google-cast-sdk/issues/list 
github.com/ivan-aguirre/chromecast_samples 
ivan-aguirre.github.io/ccast-graph/receiver.html 
ivan-aguirre.github.io/video-ccast-player/receiver.html 
G+: Google Cast Developers
Seu App na TV: Desenvolvimento 
para ChromeCast 
Obrigado!! 
Cast your questions :) 
Ivan de Aguirre 
! 
ivan.aguirre@gmail.com 
! 
Twitter: IvAguirre 
! 
G+: plus.google.com/+IvanAguirreBr

Weitere ähnliche Inhalte

Ähnlich wie Chromecast na Qcon RJ

MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de Aguirre
MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de AguirreMobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de Aguirre
MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de AguirreDextra
 
Treze ferramentas/frameworks para desenvolvimento Android
Treze ferramentas/frameworks para desenvolvimento AndroidTreze ferramentas/frameworks para desenvolvimento Android
Treze ferramentas/frameworks para desenvolvimento AndroidAdriano Rocha
 
Treze ferramentas/frameworks para desenvolvimento android
Treze ferramentas/frameworks para desenvolvimento androidTreze ferramentas/frameworks para desenvolvimento android
Treze ferramentas/frameworks para desenvolvimento androidRicardo Longa
 
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWS
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWSAcelerando a entrega de software com as ferramentas de desenvolvimento da AWS
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWSAmazon Web Services LATAM
 
Melhores práticas de CI/CD na construção de aplicações modernas
Melhores práticas de CI/CD na construção de aplicações modernasMelhores práticas de CI/CD na construção de aplicações modernas
Melhores práticas de CI/CD na construção de aplicações modernasAmazon Web Services LATAM
 
HTML 5, CSS 3 e o futuro da Web
HTML 5, CSS 3 e o futuro da WebHTML 5, CSS 3 e o futuro da Web
HTML 5, CSS 3 e o futuro da WebDiego Pessoa
 
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...Amazon Web Services LATAM
 
Seminário sd android_exemplos
Seminário sd android_exemplosSeminário sd android_exemplos
Seminário sd android_exemplosCalvin Rodrigues
 
Levando Serverless para o Edge - ARC301 - Sao Paulo Summit
Levando Serverless para o Edge -  ARC301 - Sao Paulo SummitLevando Serverless para o Edge -  ARC301 - Sao Paulo Summit
Levando Serverless para o Edge - ARC301 - Sao Paulo SummitAmazon Web Services
 
Introdução ao Google TV
Introdução ao Google TVIntrodução ao Google TV
Introdução ao Google TVAécio Costa
 
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e Crouton
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e CroutonMinicurso sobre AndroidAnnotations, GreenDAO, EventBus e Crouton
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e CroutonRicardo Longa
 
Automatize seu processo de entrega de software com CI/CD na AWS
Automatize seu processo de entrega de software com CI/CD na AWSAutomatize seu processo de entrega de software com CI/CD na AWS
Automatize seu processo de entrega de software com CI/CD na AWSAmazon Web Services LATAM
 
TDC - Testes e Sistemas legados #quemNunca - SC/2016
TDC - Testes e Sistemas legados #quemNunca - SC/2016TDC - Testes e Sistemas legados #quemNunca - SC/2016
TDC - Testes e Sistemas legados #quemNunca - SC/2016Fernando Santiago
 
Comet - ReverseAjax com DWR - Resumo
Comet - ReverseAjax com DWR - ResumoComet - ReverseAjax com DWR - Resumo
Comet - ReverseAjax com DWR - ResumoHanderson Frota
 
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EEJavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EERodrigo Cândido da Silva
 
Zabbix e KACE, uma boa ideia, e porque não!
Zabbix e KACE, uma boa ideia, e porque não!Zabbix e KACE, uma boa ideia, e porque não!
Zabbix e KACE, uma boa ideia, e porque não!Fabio Vieira Mello
 
SESTINFO 2011 Apresentacao Android
SESTINFO 2011 Apresentacao AndroidSESTINFO 2011 Apresentacao Android
SESTINFO 2011 Apresentacao AndroidRafael Sakurai
 

Ähnlich wie Chromecast na Qcon RJ (20)

MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de Aguirre
MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de AguirreMobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de Aguirre
MobCamp 2014 :: Chromecast seu aplicativo na TV - Ivan de Aguirre
 
Treze ferramentas/frameworks para desenvolvimento Android
Treze ferramentas/frameworks para desenvolvimento AndroidTreze ferramentas/frameworks para desenvolvimento Android
Treze ferramentas/frameworks para desenvolvimento Android
 
Treze ferramentas/frameworks para desenvolvimento android
Treze ferramentas/frameworks para desenvolvimento androidTreze ferramentas/frameworks para desenvolvimento android
Treze ferramentas/frameworks para desenvolvimento android
 
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWS
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWSAcelerando a entrega de software com as ferramentas de desenvolvimento da AWS
Acelerando a entrega de software com as ferramentas de desenvolvimento da AWS
 
Melhores práticas de CI/CD na construção de aplicações modernas
Melhores práticas de CI/CD na construção de aplicações modernasMelhores práticas de CI/CD na construção de aplicações modernas
Melhores práticas de CI/CD na construção de aplicações modernas
 
HTML 5, CSS 3 e o futuro da Web
HTML 5, CSS 3 e o futuro da WebHTML 5, CSS 3 e o futuro da Web
HTML 5, CSS 3 e o futuro da Web
 
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...
Deep dive em aceleração de entrega de conteúdo, APIs e Aplicações utilizando ...
 
Seminário sd android_exemplos
Seminário sd android_exemplosSeminário sd android_exemplos
Seminário sd android_exemplos
 
Levando Serverless para o Edge - ARC301 - Sao Paulo Summit
Levando Serverless para o Edge -  ARC301 - Sao Paulo SummitLevando Serverless para o Edge -  ARC301 - Sao Paulo Summit
Levando Serverless para o Edge - ARC301 - Sao Paulo Summit
 
Introdução ao Google TV
Introdução ao Google TVIntrodução ao Google TV
Introdução ao Google TV
 
Python 08
Python 08Python 08
Python 08
 
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e Crouton
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e CroutonMinicurso sobre AndroidAnnotations, GreenDAO, EventBus e Crouton
Minicurso sobre AndroidAnnotations, GreenDAO, EventBus e Crouton
 
Automatize seu processo de entrega de software com CI/CD na AWS
Automatize seu processo de entrega de software com CI/CD na AWSAutomatize seu processo de entrega de software com CI/CD na AWS
Automatize seu processo de entrega de software com CI/CD na AWS
 
TDC - Testes e Sistemas legados #quemNunca - SC/2016
TDC - Testes e Sistemas legados #quemNunca - SC/2016TDC - Testes e Sistemas legados #quemNunca - SC/2016
TDC - Testes e Sistemas legados #quemNunca - SC/2016
 
Comet - ReverseAjax com DWR - Resumo
Comet - ReverseAjax com DWR - ResumoComet - ReverseAjax com DWR - Resumo
Comet - ReverseAjax com DWR - Resumo
 
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EEJavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
 
Zabbix e KACE, uma boa ideia, e porque não!
Zabbix e KACE, uma boa ideia, e porque não!Zabbix e KACE, uma boa ideia, e porque não!
Zabbix e KACE, uma boa ideia, e porque não!
 
Apresentação Google Android
Apresentação Google AndroidApresentação Google Android
Apresentação Google Android
 
SESTINFO 2011 Apresentacao Android
SESTINFO 2011 Apresentacao AndroidSESTINFO 2011 Apresentacao Android
SESTINFO 2011 Apresentacao Android
 
Construindo apps móveis com AWS Mobile Hub
Construindo apps móveis com AWS Mobile HubConstruindo apps móveis com AWS Mobile Hub
Construindo apps móveis com AWS Mobile Hub
 

Chromecast na Qcon RJ

  • 1. Seu App na TV: Desenvolvimento para ChromeCast Ivan de Aguirre ! ivan.aguirre@gmail.com ! Twitter: IvAguirre ! G+: plus.google.com/+IvanAguirreBr
  • 2.
  • 6. Sender App: Android iOS Chrome App
  • 7. Sender App: Android iOS Chrome App Receiver App:
  • 8. Sender App: Android iOS Chrome App Receiver App: HTML 5
  • 9. Sender App: Android iOS Chrome App Receiver App: HTML 5 <video>
  • 10. Sender App: Android iOS Chrome App Receiver App: HTML 5 <video> Registro
  • 11. Sender App: Android iOS Chrome App Receiver App: HTML 5 <video> Registro Application ID = URL
  • 12.
  • 13.
  • 14.
  • 15.
  • 17. Workflow em detalhes • Descoberta do Chromecast.
  • 18. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID.
  • 19. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID. • Envio do Application ID ao Chromecast.
  • 20. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID. • Envio do Application ID ao Chromecast. • Chromecast acessa a URL do Application ID: Receiver App no ar!!
  • 21. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID. • Envio do Application ID ao Chromecast. • Chromecast acessa a URL do Application ID: Receiver App no ar!! • Sender envia a URL para o vídeo (media channel) e/ou…
  • 22. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID. • Envio do Application ID ao Chromecast. • Chromecast acessa a URL do Application ID: Receiver App no ar!! • Sender envia a URL para o vídeo (media channel) e/ou… • Envia texto (custom channel).
  • 23. Workflow em detalhes • Descoberta do Chromecast. • (Re)Conexão com o Chromecast: sessionID. • Envio do Application ID ao Chromecast. • Chromecast acessa a URL do Application ID: Receiver App no ar!! • Sender envia a URL para o vídeo (media channel) e/ou… • Envia texto (custom channel). • Callbacks, callbacks, callbacks, callbacks…
  • 24. Por dentro do Chromecast
  • 25. Por dentro do Chromecast • Chrome Browser.
  • 26. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript.
  • 27. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript. • Limitações de memória e CPU.
  • 28. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript. • Limitações de memória e CPU. • Sem WebGL ou Chrome Extensions.
  • 29. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript. • Limitações de memória e CPU. • Sem WebGL ou Chrome Extensions. • Nada de Tabs, janelas, popups ou inputs.
  • 30. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript. • Limitações de memória e CPU. • Sem WebGL ou Chrome Extensions. • Nada de Tabs, janelas, popups ou inputs. • Suporte à WebAudio API.
  • 31. Por dentro do Chromecast • Chrome Browser. • HTML5, CSS 3, JavaScript. • Limitações de memória e CPU. • Sem WebGL ou Chrome Extensions. • Nada de Tabs, janelas, popups ou inputs. • Suporte à WebAudio API. • Uma tag <video> ativa por vez.
  • 32. developers.google.com/cast ! developers.google.com/cast/ docs/ux_guidelines ! developers.google.com/cast/ docs/design_checklist
  • 33. Sender com.android.support:appcompat-v7 ! com.android.support:mediarouter-v7 ! com.google.android.gms:play-services
  • 34. Sender GoogleApiClient.ConnectionCallbacks GoogleApiClient.OnConnectionFailedListener MediaRouter.Callback Cast.Listener ResultCallback<Cast.ApplicationConnectionResult> RemoteMediaPlayer.OnStatusUpdatedListener RemoteMediaPlayer.OnMetadataUpdatedListener ResultCallback<RemoteMediaPlayer.MediaChannelResult>
  • 35. Sender GoogleApiClient.ConnectionCallbacks GoogleApiClient.OnConnectionFailedListener MediaRouter.Callback Cast.Listener ResultCallback<Cast.ApplicationConnectionResult> RemoteMediaPlayer.OnStatusUpdatedListener RemoteMediaPlayer.OnMetadataUpdatedListener ResultCallback<RemoteMediaPlayer.MediaChannelResult>
  • 37. Sender + CastCompanionLibrary public class MyApplication extends Application { private static VideoCastManager mCastMgr; public static VideoCastManager getVideoCastManager(Context ctx) { if (null == mCastMgr) { ! mCastMgr = VideoCastManager.initialize(ctx, "XYZ1234", null, /* activity com player */ null /* namespace */); mCastMgr.enableFeatures(… ! } mCastMgr.setContext(ctx); return mCastMgr; } }
  • 38. Sender + CastCompanionLibrary public class MainActivity extends ActionBarActivity { private VideoCastManager mVideoCastManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BaseCastManager.checkGooglePlayServices(this); mVideoCastManager = MyApplication.getVideoCastManager( this); mVideoCastManager.reconnectSessionIfPossible(this, true, 5 /*sec*/); } }
  • 39. Sender + CastCompanionLibrary public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); ! getMenuInflater().inflate(R.menu.main, menu); ! mVideoCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item); ! return true; }
  • 40. Sender + CastCompanionLibrary MediaMetadata mediaMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); mediaMetadata.putString(MediaMetadata.KEY_TITLE, "Title: Chromecast na QCON RJ 2014"); mediaMetadata.putString(MediaMetadata.KEY_SUBTITLE, ""); mediaMetadata.putString(MediaMetadata.KEY_STUDIO, "Ivan de Aguirre Productions"); MediaInfo mediaInfo = new MediaInfo.Builder( "https://d2k4ls0ga9ks2.cloudfront.net/VID_20140727_225510282.mp4") .setContentType("video/mp4") .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setMetadata(mediaMetadata) .build(); mVideoCastManager.startCastControllerActivity(this, mediaInfo, 0, true);
  • 42. Receiver • Default Receiver.
  • 43. Receiver • Default Receiver. • Styled Receiver.
  • 44. Receiver • Default Receiver. • Styled Receiver. • Custom Receiver.
  • 45. Custom Receiver Mínimo <html> <head> <title>Example minimum receiver</title> <script src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></ script> </head> <body> <video id='media'/> <script> ... </script> </body> </html>
  • 46. Custom Receiver Mínimo <script> window.onload = function() { window.mediaElement=document.getElementById('media'); ! window.mediaManager = new cast.receiver.MediaManager( window.mediaElement); ! window.castReceiverManager = cast.receiver .CastReceiverManager.getInstance(); ! window.castReceiverManager.start(); } </script>
  • 48. Exemplo 1 • Custom Receiver para exibir propaganda e notificações no telefone.
  • 49. Exemplo 1 • Custom Receiver para exibir propaganda e notificações no telefone. • Envia URL do vídeo pelo Media Channel.
  • 50. Exemplo 1 • Custom Receiver para exibir propaganda e notificações no telefone. • Envia URL do vídeo pelo Media Channel. • Envia texto pelo Custom Channel com as notificações.
  • 51. Exemplo 1 • Custom Receiver para exibir propaganda e notificações no telefone. • Envia URL do vídeo pelo Media Channel. • Envia texto pelo Custom Channel com as notificações. • No Receiver exibe propagandas.
  • 52. Exemplo 1 - Sender public class MyApplication extends Application { private static VideoCastManager mCastMgr; public static VideoCastManager getVideoCastManager(Context ctx) { if (null == mCastMgr) { mCastMgr = VideoCastManager.initialize(ctx, "XYZ1234", "urn:x-­‐cast:org.gcastsamples.castnotifications"); // configurar opções... } ! mCastMgr.setContext(ctx); return mCastMgr; } }
  • 53. Exemplo 1 - Sender public class MyNotificationListenerService extends NotificationListenerService { @Override public void onNotificationPosted(StatusBarNotification statusBarNotification) { String msg = String.valueOf( statusBarNotification.getNotification().tickerText); ! try { ! MyApplication.getVideoCastManager(getApplicationContext()) .sendDataMessage(msg); ! } catch (TransientNetworkDisconnectionException e) { Log.e("NotificationListenerService", "Can't send message", e); } catch (NoConnectionException e) { Log.e("NotificationListenerService", "Can't send message", e); } } }
  • 54. Exemplo 1 - Receiver <div id="notification_banner" class="alert alert-­‐info" role="alert"> <h4>New Notification from your phone!!</h4> <p id="notification_text">Test!!!</p> </div> ! <div id="ad_banner" class="alert alert-­‐warning" role="alert"> <h4 id="ad_text">New Notification from your phone!!</h4> </div> ! <video id="media"/>
  • 55. Exemplo 1 - Receiver window.mediaElement = document.getElementById('media'); window.mediaElement.addEventListener('playing', function(event) { advertising.start(); }); ! window.mediaManager = new cast.receiver.MediaManager(window.mediaElement); window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance(); ! window.castReceiverManager.onSenderDisconnected = function(event) { if (window.castReceiverManager.getSenders().length == 0 && event.reason == cast.receiver.system.DisconnectReason.REQUESTED_BY_SENDER) { advertising.stop(); window.close(); }
  • 56. Exemplo 1 - Receiver var nms = 'urn:x-­‐cast:org.gcastsamples.castnotifications'; var customMessageBus = window.castReceiverManager .getCastMessageBus(nms); customMessageBus.onMessage = function(event) { showNotification(event.data); } window.castReceiverManager.start();
  • 58. Exemplo 2 • Custom Receiver para exibir um gráfico.
  • 59. Exemplo 2 • Custom Receiver para exibir um gráfico. • www.flotcharts.org
  • 60. Exemplo 2 • Custom Receiver para exibir um gráfico. • www.flotcharts.org • A página do Custom Receiver quando acessada pelo Chromecast é um Receiver.
  • 61. Exemplo 2 • Custom Receiver para exibir um gráfico. • www.flotcharts.org • A página do Custom Receiver quando acessada pelo Chromecast é um Receiver. • A página do Custom Receiver quando acessada pelo Browser é uma aplicação Web.
  • 63. Exemplo 2 - Sender public class MyApplication extends Application { ! private static DataCastManager mCastMgr; public static final String NAME_SPACE = "urn:x-­‐cast:org.gcastsamples.plotandcast"; public static DataCastManager getDataCastManager(Context ctx) { if (null == mCastMgr) { mCastMgr = DataCastManager.initialize(ctx,"XYZ123", NAME_SPACE); } ! mCastMgr.setContext(ctx); return mCastMgr; } }
  • 64. Exemplo 2 - Sender String json = getData(); ! mDataCastManager.sendDataMessage( json, MyApplication.NAME_SPACE);
  • 65. Exemplo 2 - Receiver <body> <form id="plot_inputs"> … </form> <div id="content"> <div class="chart-­‐container"> <div id="placeholder" class="chart-­‐placeholder"></div> </div> </div> </body>
  • 66. Exemplo 2 - Receiver if (navigator.userAgent.indexOf('CrKey') >= 0) { ! $('#plot_inputs').hide(); // form inputs $('.chart-­‐container').addClass('chart-­‐container-­‐for-­‐tv'); ! startChromeCastMode(); ! } else { ! startBrowserMode(); ! }
  • 67. Exemplo 2 - Receiver function startChromeCastMode() { window.onload = function() { window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance(); var nms='urn:x-­‐cast:org.gcastsamples.plotandcast'; var customMessageBus = window.castReceiverManager.getCastMessageBus(nms); customMessageBus.onMessage = function(event) { var json = $.parseJSON(event.data);; plot(json); } window.castReceiverManager.start(); } }
  • 69. Mirror e Presentation • Transmissão de Tela (Mirroring).
  • 70. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+:
  • 71. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+: • Em modo Mirror renderizar um Layout na TV (não há receiver).
  • 72. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+: • Em modo Mirror renderizar um Layout na TV (não há receiver). • Wireless Display.
  • 73. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+: • Em modo Mirror renderizar um Layout na TV (não há receiver). • Wireless Display. • Suporta Miracast.
  • 74. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+: • Em modo Mirror renderizar um Layout na TV (não há receiver). • Wireless Display. • Suporta Miracast. • E Chromecast :)
  • 75. Mirror e Presentation • Transmissão de Tela (Mirroring). • Presentation API: API Level 17, Android 4.2+: • Em modo Mirror renderizar um Layout na TV (não há receiver). • Wireless Display. • Suporta Miracast. • E Chromecast :) • Plugin do Chromecast para Chrome: espelha aba e tela.
  • 78. Exemplo 3 - Mirror e Presentation
  • 79. Exemplo 3 - Mirror e Presentation •Aplicação insere elementos em uma lista.
  • 80. Exemplo 3 - Mirror e Presentation •Aplicação insere elementos em uma lista. • A lista é renderizada e manipulada na TV.
  • 81. Exemplo 3 - Mirror e Presentation •Aplicação insere elementos em uma lista. • A lista é renderizada e manipulada na TV. •Não é casting!!
  • 82. Exemplo 3 - Mirror e Presentation public class ListPresentation extends Presentation { private RecyclerView mRecyclerView; private RecyclerView.LayoutManager mLayoutManager; private MyAdapter mAdapter; public ListPresentation(Context context, Display display) { super(context, display); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Context ctx = getContext(); Resources r = ctx.getResources(); setContentView(R.layout.presentation); mRecyclerView = (RecyclerView) findViewById(R.id.list); mLayoutManager = new LinearLayoutManager(ctx); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mAdapter = new MyAdapter(); mRecyclerView.setAdapter(mAdapter); } ...
  • 83. MediaRouter mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); Display presentationDisplay = route != null ? route.getPresentationDisplay() : null; if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { mPresentation.dismiss(); mPresentation = null; } if (mPresentation == null && presentationDisplay != null) { mPresentation = new ListPresentation(this, presentationDisplay); mPresentation.setOnDismissListener(mOnDismissListener); try { mPresentation.show(); } catch (WindowManager.InvalidDisplayException ex) { Log.w(TAG, "Display was removed in the meantime.", ex); mPresentation = null; } } Exemplo 3 - Mirror e Presentation
  • 84. MediaRouter mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); Display presentationDisplay = route != null ? route.getPresentationDisplay() : null; if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { mPresentation.dismiss(); mPresentation = null; } if (mPresentation == null && presentationDisplay != null) { mPresentation = new ListPresentation(this, presentationDisplay); mPresentation.setOnDismissListener(mOnDismissListener); try { mPresentation.show(); } catch (WindowManager.InvalidDisplayException ex) { Log.w(TAG, "Display was removed in the meantime.", ex); mPresentation = null; } } Exemplo 3 - Mirror e Presentation android.media.MediaRouter não é app compact!!
  • 85. MediaRouter mMediaRouter ROUTE_TYPE_LIVE_AUDIO = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); Display presentationDisplay = route != null ? route.getPresentationDisplay() : null; if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { mPresentation.dismiss(); mPresentation = null; } if (mPresentation == null && presentationDisplay != null) { mPresentation = new ListPresentation(this, presentationDisplay); mPresentation.setOnDismissListener(mOnDismissListener); try { mPresentation.show(); } catch (WindowManager.InvalidDisplayException ex) { Log.w(TAG, "Display was removed in the meantime.", ex); mPresentation = null; } } Exemplo 3 - Mirror e Presentation android.media.MediaRouter não é app compact!!
  • 91. Developer Tools: <chromecast ip>:9222 • window.location.reload(true);
  • 92. Developer Tools: <chromecast ip>:9222 • window.location.reload(true); • window.location.replace('http://myhost.com/receiver.html');
  • 93. FAQ
  • 95. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção.
  • 96. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. • Múltiplas conexões ao receiver.
  • 97. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. • Múltiplas conexões ao receiver. • Segurança: é preciso implementar os mecanismos.
  • 98. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. • Múltiplas conexões ao receiver. • Segurança: é preciso implementar os mecanismos. • Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth Streaming, DRM, etc..
  • 99. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. • Múltiplas conexões ao receiver. • Segurança: é preciso implementar os mecanismos. • Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth Streaming, DRM, etc.. • CORS.
  • 100. FAQ • Sender/Receiver: HTTPS. • URL do Receiver: HTTP em desenvolvimento, HTTPS em produção. • Múltiplas conexões ao receiver. • Segurança: é preciso implementar os mecanismos. • Media Player Library (Beta): Live Streaming, MPEG-DASH, Smooth Streaming, DRM, etc.. • CORS. • Não esqueçam do iOS :)
  • 101. Futuro
  • 103. Futuro • Google TV? • Chrome OS: integração no Google Drive na build de desenvolvimento.
  • 104. Futuro • Google TV? • Chrome OS: integração no Google Drive na build de desenvolvimento. • Conexão fora da mesma rede Wifi.
  • 105. Referências developers.google.com/cast cast.google.com/publish github.com/googlecast code.google.com/p/google-cast-sdk/issues/list github.com/ivan-aguirre/chromecast_samples ivan-aguirre.github.io/ccast-graph/receiver.html ivan-aguirre.github.io/video-ccast-player/receiver.html G+: Google Cast Developers
  • 106. Seu App na TV: Desenvolvimento para ChromeCast Obrigado!! Cast your questions :) Ivan de Aguirre ! ivan.aguirre@gmail.com ! Twitter: IvAguirre ! G+: plus.google.com/+IvanAguirreBr