integrando sua app android com chromecast

Post on 22-Jun-2015

238 Views

Category:

Mobile

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Palestra ministrada no segundo Mobile Day Ci&T, ocorrido em 27/09/2014

TRANSCRIPT

Integrando sua app Android com Chromecast

Athila Santosathila@ciandt.com

Formado em Engenharia da Computação pela Universidade Federal de Itajubá em 2007. Trabalho com desenvolvimento Mobile desde então e com Android desde 2009 (Android 1.5)

26

Ready to cast!

Cast device

Cast device

Provedor de conteúdo

Cast device

Renderizador

Provedor de conteúdo

Cast device

Renderizador

Controle

Provedor de conteúdo

Cast devices no mercado

Amazon Fire TV

Roku 3 Apple TV Google Chromecast

Processador Quad core Dual core Single core Single core

Memória 2 GB 512 MB 512 MB 512 MB

ControleComando por voz; controle

físico

Controle físico; app iOS

disponível

Controle físico; app iOS

Controlado por app (iOS, Android, Chrome)

HDMI SIM SIM SIM SIM

Preço $99 $99 $99 $35

● Sender app

Chromecast: Requisitos

● Sender app

Chromecast: Requisitos

● Receiver app

● Sender app

Chromecast: Requisitos

● Receiver app

● Sender app

Chromecast: Requisitos

● Receiver app

Default Receiver (pronto para uso)

● Sender app

Chromecast: Requisitos

Styled Media Receiver

● Receiver app

Default Receiver (pronto para uso)

Custom Receiver

● Sender app

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Chromecast: Requisitos

Styled Media Receiver

● Receiver app

Default Receiver (pronto para uso)

Custom Receiver

● Sender app

Chromecast: Requisitos

Styled Media Receiver

● Receiver app

Default Receiver (pronto para uso)

Custom Receiver

● Sender app

Chromecast: Requisitos

Web browser limitado!

Chromecast: Application lifecycle

Chromecast: Application lifecycle

Chromecast: Application lifecycle

Chromecast: Application lifecycle

App ID

Chromecast: Application lifecycle

App ID

App ID

Chromecast: Application lifecycle

App ID

App ID

URL

Chromecast: Application lifecycle

App ID

App ID

URL

URL

Chromecast: Application lifecycle

App ID

App ID

URL

URL

HTML

Chromecast: Application lifecycle

App ID

App ID

URL

URL

HTML

Canal de dados

The sender app

Sender app: Dependências

 

 

 

Sender app: Dependências

● Android Support Library v7

 

 

Sender app: Dependências

● Android Support Library v7

● Android Support Media Router

Library

 

Sender app: Dependências

● Android Support Library v7

● Android Support Media Router

Library

● Google Play Services

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Sender app: Descoberta de dispositivos

Sender app: Descoberta de dispositivos

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" >

<item android:id="@+id/media_route_menu_item" android:title="@string/media_route_menu_title" app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider" app:showAsAction="always"/></menu>

Sender app: Descoberta de dispositivos

Descoberta de dispositivos: Media Router Selector

Descoberta de dispositivos: Media Router Selector

public class MediaRouterPlaybackActivity extends ActionBarActivity { private MediaRouteSelector mSelector;

@Override protected void onCreate(Bundle savedInstanceState) { (...) // Create a route selector for the type of routes your app supports. mSelector = new MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO) .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO) .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build();

(...) }}

Descoberta de dispositivos: Media Router Selector

public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);

// Inflate the menu and configure the media router action provider. getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);

// Attach the MediaRouteSelector to the menu item MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem); mediaRouteActionProvider.setRouteSelector(mSelector);

// Return true to show the menu. return true;}

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Gerenciamento de sessão: Media Router Callback

private final MediaRouter.Callback mMediaRouterCallback = new MediaRouter.Callback() {

@Override public void onRouteSelected(MediaRouter router, RouteInfo route) { }

@Override public void onRouteUnselected(MediaRouter router, RouteInfo route) { }

@Override public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo route) { }}

Gerenciamento de sessão: Media Router Callback

public class MediaRouterPlaybackActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { mMediaRouter = MediaRouter.getInstance(this); }

public void onStart() { mMediaRouter.addCallback(mSelector, mMediaRouterCallback,

MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); }

public void onStop() { mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }}

Gerenciamento de sessão: Media Router Callback

public class MediaRouterPlaybackActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { mMediaRouter = MediaRouter.getInstance(this); }

public void onStart() { mMediaRouter.addCallback(mSelector, mMediaRouterCallback,

MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); }

public void onStop() { mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }}

Gerenciamento de sessão: Media Router Callback

public class MediaRouterPlaybackActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { mMediaRouter = MediaRouter.getInstance(this); }

public void onStart() { mMediaRouter.addCallback(mSelector, mMediaRouterCallback,

MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); }

public void onStop() { mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }}

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Sender app: Os passos para o sucesso...

1. Descoberta de dispositivos

2. Gerenciamento de sessão

3. Transimissão de dados

Transmissão de dados: Mensagem genérica

Cast.CastApi.sendMessage (com.google.android.gms.common.api.GoogleApiClient, NAMESPACE, message)

.setResultCallback (new ResultCallback<Status>() {

@Overridepublic void onResult(Status result) {

if (!result.isSuccess()) { Log.e(TAG, "Sending message failed"); }}});

Transmissão de dados: Remote playback

protected void onCreate(Bundle savedInstanceState) { Bundle mediaInfo = new Bundle(); mediaInfo.putString(MediaMetadata.KEY_TITLE, "Big Buck Bunny"); mediaInfo.putString(MediaMetadata.KEY_SUBTITLE, "Blender Foundation"); mediaInfo.putString(MediaMetadata.KEY_STUDIO, "Fusce id nisi turpis. Praesent viverra bibendum semper. Donec tristique, orci");

(...)}

Transmissão de dados: Remote playback

public void onRouteSelected(MediaRouter router, RouteInfo route) { mRemotePlaybackClient = new RemotePlaybackClient(this, route); mRemotePlaybackClient.play(Uri.parse("http://meu_video.mp4"), "video/mp4", mediaInfo, 0, null, new ItemActionCallback() {

@Override public void onResult(Bundle data, String sessionId, MediaSessionStatus sessionStatus, String itemId, MediaItemStatus itemStatus) { logStatus("play: succeeded for item " + itemId); } @Override public void onError(String error, int code, Bundle data) { } });}

Google Cast User Guidelines

Google Cast User Guidelines

https://developers.google.com/cast/docs/design_checklist#sender

CastCompanionLibrary - Registrando receiver app

public class CastApplication extends Application { private static VideoCastManager mCastMgr = null;

public static VideoCastManager getCastManager(Context context) { if (null == mCastMgr) { mCastMgr = VideoCastManager.initialize(context, APPLICATION_ID, null, null); } mCastMgr.setContext(context); return mCastMgr; }}

CastCompanionLibrary - Registrando receiver app

public class CastApplication extends Application { private static VideoCastManager mCastMgr = null;

public static VideoCastManager getCastManager(Context context) { if (null == mCastMgr) { mCastMgr = VideoCastManager.initialize(context, APPLICATION_ID, null, null); } mCastMgr.setContext(context); return mCastMgr; }} Default Receiver App:

CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" >

<item android:id="@+id/media_route_menu_item" android:title="@string/media_route_menu_title" app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider" app:showAsAction="always"/></menu>

Sender app: Descoberta de dispositivos

CastCompanionLibrary - Descoberta de devices

public class PlayerActivity extends ActionBarActivity { private VideoCastManager mCastManager; private MediaInfo mSelectedMedia; private VideoCastConsumerImpl mCastConsumer;

protected void onCreate(Bundle savedInstanceState) { mCastManager = CastApplication.getCastManager(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.main, menu); mCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item); return true; }}

CastCompanionLibrary - Gerenciando sessãoprotected void onCreate(Bundle savedInstanceState) { mCastConsumer = new VideoCastConsumerImpl() { public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) { } public void onApplicationDisconnected(int errorCode) { } public void onDisconnected() { } public void onRemoteMediaPlayerMetadataUpdated() { } public void onFailed(int resourceId, int statusCode) { } public void onConnectionSuspended(int cause) { } public void onConnectivityRecovered() { } }; }protected void onResume() { super.onResume(); mCastManager.addVideoCastConsumer(mCastConsumer); }

protected void onCreate(Bundle savedInstanceState) { Bundle mediaInfo = new Bundle(); mediaInfo.putString(MediaMetadata.KEY_TITLE, "Big Buck Bunny"); mediaInfo.putString(MediaMetadata.KEY_SUBTITLE, "Blender Foundation"); mediaInfo.putString(MediaMetadata.KEY_STUDIO, "Fusce id nisi turpis. Praesent viverra bibendum semper. Donec tristique, orci"); mediaInfo.putString(com.google.sample.castcompanionlibrary.utils.Utils.KEY_URL, http://url.mp4); mediaInfo.putString(com.google.sample.castcompanionlibrary.utils.Utils.KEY_CONTENT_TYPE, "video/mp4"); ArrayList<String> images = new ArrayList<String>(); images.add("http://image_url_480"); images.add("http://image_url_720"); mediaInfo.putStringArrayList(com.google.sample.castcompanionlibrary.utils.Utils.KEY_IMAGES, images); mSelectedMediaInfo = com.google.sample.castcompanionlibrary.utils.Utils.toMediaInfo(mediaInfo);}

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_TITLE, "Big Buck Bunny");

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_TITLE, "Big Buck Bunny");

CastCompanionLibrary - Reproduzindo vídeo remoto

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_SUBTITLE, "Blender Foundation");

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_SUBTITLE, "Blender Foundation");

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_STUDIO, "Fusce id nisi turpis. Praesent viverra bibendum semper. Donec tristique, orci");

CastCompanionLibrary - Reproduzindo vídeo remoto

mediaInfo.putString(MediaMetadata.KEY_STUDIO, "Fusce id nisi turpis. Praesent viverra bibendum semper. Donec tristique, orci");

CastCompanionLibrary - Reproduzindo vídeo remoto

images.add("http://image_url_480");

CastCompanionLibrary - Reproduzindo vídeo remoto

images.add("http://image_url_480");

CastCompanionLibrary - Reproduzindo vídeo remoto

public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) { if (null != mSelectedMedia) { mCastManager.startCastControllerActivity(this, mSelectedMedia, 0, true); finish(); return; }}

CastCompanionLibrary - Reproduzindo vídeo remoto

Brindes da CCL

CastControllerActivity

CCL - CastControllerActivity

CCL - CastControllerActivity

CCL - CastControllerActivity

images.add("http://image_url_720");

CCL - CastControllerActivity

<activity android:name="com.google.sample.castcompanionlibrary.cast.player.VideoCastControllerActivity" android:launchMode="singleTask" android:screenOrientation="portrait" android:theme="@style/Theme.CastVideoOverlayYellow" > <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="<parentActivity>" />

<intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity>

MiniController

CCL - MiniController

CCL - MiniController

CCL - MiniController

<com.google.sample.castcompanionlibrary.widgets.MiniController android:id="@+id/miniController1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:visibility="gone" > </com.google.sample.castcompanionlibrary.widgets.MiniController>

CCL - MiniController

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

// -- Adding MiniController mMini = (MiniController) findViewById(R.id.miniController1); mCastManager.addMiniController(mMini);}protected void onDestroy() { if (null != mCastManager) { mCastManager.removeMiniController(mMini); } super.onDestroy();}

OnGoing Notification

CCL - OnGoing Notification

CCL - OnGoing Notification

CCL - OnGoing Notification<receiver android:name="com.google.sample.castcompanionlibrary.remotecontrol.VideoIntentReceiver" > <intent-filter> <action android:name="com.google.sample.castcompanionlibrary.action.toggleplayback" /> <action android:name="com.google.sample.castcompanionlibrary.action.stop" /> </intent-filter></receiver>

<service android:name="com.google.sample.castcompanionlibrary.notification.VideoCastNotificationService" android:exported="false" > <intent-filter> <action android:name="com.google.sample.castcompanionlibrary.action.toggleplayback" /> <action android:name="com.google.sample.castcompanionlibrary.action.stop" /> <action android:name="com.google.sample.castcompanionlibrary.action.notificationvisibility" /> </intent-filter></service>

CCL - OnGoing Notificationprotected void onResume() { mCastManager = CastApplication.getCastManager(this); mCastManager.incrementUiCounter();}protected void onPause() { mCastManager.decrementUiCounter();}

public class CastApplication extends Application { private static VideoCastManager mCastMgr = null;

public static VideoCastManager getCastManager(Context context) { mCastMgr = VideoCastManager.initialize(context, APPLICATION_ID, null, null); mCastMgr.enableFeatures(VideoCastManager.FEATURE_NOTIFICATION ); return mCastMgr; }}

Lock Screen

CCL - Lock Screen

CCL - LockScreen

public class CastApplication extends Application { private static VideoCastManager mCastMgr = null;

public static VideoCastManager getCastManager(Context context) { mCastMgr = VideoCastManager.initialize(context, APPLICATION_ID, null, null); mCastMgr.enableFeatures(VideoCastManager.FEATURE_NOTIFICATION | VideoCastManager.FEATURE_LOCKSCREEN); return mCastMgr; }}

CCL RULES!!!!!

Obrigado!

Athila Santosathila@ciandt.comathilahs@gmail.com

br.linkedin.com/pub/athila-henrique-dos-santos/6/41/744/

top related