SlideShare una empresa de Scribd logo
1 de 130
Descargar para leer sin conexión
Google Cast with Android
How to Implement Google Cast into Android Apps
+Angelo Rüggeberg
@s3xy4ngyc
agenda
-  Introduction to Google Cast
-  Connecting an Android App to an
Cast App
-  Launching the Cast App
-  Interacting with the Cast App
-  using the CastCompanionLibrary
for Media
Introduction to Google Cast
Biggest, most beautiful screen in the house...
Your app on the TV!
Simple to get
started with
the SDK
Connecting technology
Start with your
existing app
e.g. Phone app
e.g. Phone app
e.g. Phone app
Tablets
Web Apps
Your app is ‘The Sender’
Receiving
device
Receiver app runs on
Cast receiving device
Cast SDK app
looks for
Cast devices
Cast icon shown
on discovery of
Cast devices
Selection activates
connected icon look
developers.google.com/cast/docs/ux_guidelines
Consistent UX fully
documented
developers.google.com/cast/
docs/ux_guidelines
●  Selecting Cast Device
●  Pausing & Scrubbing
●  Visual Consistency
Sender triggers Receiver loading
https://…
Content loads direct
from the cloud
https://…
Sender manages
playback control
developers.google.com/cast/docs/receiver_apps
Images
Leader
Board
1st Scotty 145
2nd Andrea 109
3rd Ralph 94
developers.google.com/cast/docs/downloads
Connecting an Android App to an Cast App
Environment:
●  Real Device
○  with Google Play Services
Installed
●  Cast Device
○  e.g. Chromecast
Prequesites
Dependencies:
play-services-cast
Handles Connection to Cast
'com.google.android.gms:play-services-cast:8.3.0'
support-media-router
Button to Connect to Cast
'com.android.support:mediarouter-v7:23.1.0'
Dependencies - build.gradle
dependencies {
compile 'com.android.support:mediarouter-v7:23.1.0'
compile 'com.google.android.gms:play-services-cast:8.3.0'
}
Permissions - Manifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Adding Media Route Button via Menu
<?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>
Adding Media Route Button via Menu
<?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>
Adding Media Route Button to an Layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:mediaRouteTypes="user" />
…
</RelativeLayout>
Adding Media Route Button to an Layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:mediaRouteTypes="user" />
…
</RelativeLayout>
Adding Media Route Button to an Layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:mediaRouteTypes="user" />
…
</RelativeLayout>
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
The Button added To the Layout
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
The Media Router.
This handles the Connection to our Cast Device
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
The Route Selector.
This is the Configuration for our Connection
e.g the Device to Interact with
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
The Router Callbacks.
These Callbacks are used to Notify the
Application on Select and Deselction of an
Device Route and enables us to react to
these events e.g by printing the Connected
Device to the User.
Fields - MainActivity.java
private MediaRouteButton mMediaRouteButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
The Cast Device we are Connected to.
It contains Informations like Device Name,
Model, Capabilities, etc.
Initializing - MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mConnectionStatus = (TextView) findViewById(R.id.text_connection);
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
initCast();
}
Initializing - MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mConnectionStatus = (TextView) findViewById(R.id.text_connection);
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
initCast();
}
Initializing - MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mConnectionStatus = (TextView) findViewById(R.id.text_connection);
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
initCast();
}
Initializing - MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mConnectionStatus = (TextView) findViewById(R.id.text_connection);
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
initCast();
}
Initializing - MainActivity.java
private void initCast() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
}
Initializing - MainActivity.java
private void initCast() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(
CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id)))
.build();
}
Initializing - MainActivity.java
private void initCast() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(
CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id)))
.build();
}
The Cast Application ID.
E.g “794B7BBF” (Cast Sample Helloworld)
Initializing - MainActivity.java
private void initCast() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent.categoryForCast(getResources()
.getString(R.string.app_id)))
.build();
// Set the MediaRouteButton selector for device discovery.
mMediaRouteButton.setRouteSelector(mMediaRouteSelector);
}
Initializing - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider
= (MediaRouteActionProvider) MenuItemCompat
.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
Initializing - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider
= (MediaRouteActionProvider) MenuItemCompat
.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
Initializing - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider
= (MediaRouteActionProvider) MenuItemCompat
.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
Initializing - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider
= (MediaRouteActionProvider) MenuItemCompat
.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
Adding Callbacks - MainActivity.java
private void initCast() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent.categoryForCast(getResources()
.getString(R.string.app_id)))
.build();
// Set the MediaRouteButton selector for device discovery.
mMediaRouteButton.setRouteSelector(mMediaRouteSelector);
mMediaRouterCallback = new MyMediaRouterCallback();
}
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Called after we Selected an
Cast Device we want to
Connect with.
This does not mean we are
Connected to the Cast
Application yet!
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Called after we Decided to
Disconnect from an Cast
Device.
This does not mean we are
Disconnected from the
Application yet!
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Adding Callbacks - MainActivity.java
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName());
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
mSelectedDevice = null;
mConnectionStatus.setText("Not Connected");
}
}
Starting Discovery - MainActivity.java
@Override
protected void onStart() {
super.onStart();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
@Override
protected void onStop() {
// End media router discovery
mMediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
Starting Discovery - MainActivity.java
@Override
protected void onStart() {
super.onStart();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
@Override
protected void onStop() {
// End media router discovery
mMediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
Starting Discovery - MainActivity.java
@Override
protected void onStart() {
super.onStart();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
@Override
protected void onStop() {
// End media router discovery
mMediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
Demo
Launching the Cast Application
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
The Api Client is used to Interact with The Chromecast
e.g. Sending Messages
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
Our Callbacks to Notify us about Connection Events
e.g. disconnection
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
The Connection Callbacks.
e.G. we get disconnected due to application
errors
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
Our Callback if the connection Fails
New Fields - MainActivity.java
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private ConnectionCallbacks mConnectionCallbacks;
private ConnectionFailedListener mConnectionFailedListener;
private boolean mApplicationStarted;
private boolean mWaitingForReconnect;
private String mSessionId;
We keep Some Information for our
Application stored in these Fields
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() {
@Override
public void onApplicationDisconnected(int errorCode) {
Log.d(TAG, "application has stopped");
teardown(true);
}
};
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
}
Launching the Cast Application - MainActivity.java
private void launchReceiver() {
mCastListener = new Cast.Listener() { … };
mConnectionCallbacks = new ConnectionCallbacks();
mConnectionFailedListener = new ConnectionFailedListener();
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder(mSelectedDevice, mCastListener);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
mApiClient.connect();
}
Launching the Cast Application - MainActivity.java
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
@Override
public void onConnected(Bundle connectionHint) {
...
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
.setResultCallback(
new ResultCallback<Cast.ApplicationConnectionResult>() {
@Override
public void onResult(Cast.ApplicationConnectionResult result) {
…
}
}
Launching the Cast Application - MainActivity.java
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
@Override
public void onConnected(Bundle connectionHint) {
...
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
.setResultCallback(
new ResultCallback<Cast.ApplicationConnectionResult>() {
@Override
public void onResult(Cast.ApplicationConnectionResult result) {
…
}
}
Launching the Cast Application - MainActivity.java
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result .getApplicationMetadata();
mSessionId = result.getSessionId();
mApplicationStarted = true;
} else {
Log.e(TAG, "application could not launch");
teardown(true);
}
Launching the Cast Application - MainActivity.java
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result .getApplicationMetadata();
mSessionId = result.getSessionId();
mApplicationStarted = true;
} else {
Log.e(TAG, "application could not launch");
teardown(true);
}
Launching the Cast Application - MainActivity.java
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result .getApplicationMetadata();
mSessionId = result.getSessionId();
mApplicationStarted = true;
} else {
Log.e(TAG, "application could not launch");
teardown(true);
}
Launching the Cast Application - MainActivity.java
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result .getApplicationMetadata();
mSessionId = result.getSessionId();
mApplicationStarted = true;
} else {
Log.e(TAG, "application could not launch");
teardown(true);
}
Launching the Cast Application - MainActivity.java
private void teardown(boolean selectDefaultRoute) {
if (mApiClient != null) {
if (mApplicationStarted) {
if (mApiClient.isConnected() || mApiClient.isConnecting()) {
Cast.CastApi.stopApplication(mApiClient, mSessionId);
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
Launching the Cast Application - MainActivity.java
private void teardown(boolean selectDefaultRoute) {
if (mApiClient != null) {
if (mApplicationStarted) {
if (mApiClient.isConnected() || mApiClient.isConnecting()) {
Cast.CastApi.stopApplication(mApiClient, mSessionId);
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
Launching the Cast Application - MainActivity.java
private void teardown(boolean selectDefaultRoute) {
if (mApiClient != null) {
if (mApplicationStarted) {
if (mApiClient.isConnected() || mApiClient.isConnecting()) {
Cast.CastApi.stopApplication(mApiClient, mSessionId);
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
Launching the Cast Application - MainActivity.java
private void teardown(boolean selectDefaultRoute) {
if (mApiClient != null) {
if (mApplicationStarted) {
if (mApiClient.isConnected() || mApiClient.isConnecting()) {
Cast.CastApi.stopApplication(mApiClient, mSessionId);
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
Demo
Interacting with the Cast Application
Sending Messages - MainActivity.java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
public String getNamespace() {
return getString(R.string.namespace);
}
@Override
public void onMessageReceived(CastDevice castDevice, String namespace,
String message) {
}
}
Sending Messages - MainActivity.java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
public String getNamespace() {
return getString(R.string.namespace);
}
@Override
public void onMessageReceived(CastDevice castDevice, String namespace,
String message) {
}
}
Sending Messages - MainActivity.java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
public String getNamespace() {
return getString(R.string.namespace);
}
@Override
public void onMessageReceived(CastDevice castDevice, String namespace,
String message) {
}
}
Our Custom Namespace. This is defined in our
reciever app.
e.g. urn:x-cast:com.google.cast.sample.helloworld
Sending Messages - MainActivity.java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
public String getNamespace() {
return getString(R.string.namespace);
}
@Override
public void onMessageReceived(CastDevice castDevice, String namespace,
String message) {
}
}
This gets Triggered when the Reciever Sends Data
To our Client.
e.g. Updated Scores on Games
Sending Messages - MainActivity.java
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
….
// Create the custom message
// channel
mHelloWorldChannel = new HelloWorldChannel();
try {
Cast.CastApi.setMessageReceivedCallbacks(
mApiClient,
mHelloWorldChannel.getNamespace(),
mHelloWorldChannel);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel",
e);
}
Sending Messages - MainActivity.java
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
….
// Create the custom message
// channel
mHelloWorldChannel = new HelloWorldChannel();
try {
Cast.CastApi.setMessageReceivedCallbacks(
mApiClient,
mHelloWorldChannel.getNamespace(),
mHelloWorldChannel);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel",
e);
}
Sending Messages - MainActivity.java
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
….
// Create the custom message
// channel
mHelloWorldChannel = new HelloWorldChannel();
try {
Cast.CastApi.setMessageReceivedCallbacks(
mApiClient,
mHelloWorldChannel.getNamespace(),
mHelloWorldChannel);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel",
e);
}
Sending Messages - MainActivity.java
// Launch the receiver app
Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false)
….
// Create the custom message
// channel
mHelloWorldChannel = new HelloWorldChannel();
try {
Cast.CastApi.setMessageReceivedCallbacks(
mApiClient,
mHelloWorldChannel.getNamespace(),
mHelloWorldChannel);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel",
e);
}
Sending Messages - MainActivity.java
private void sendMessage(String message) {
if (mApiClient != null && mHelloWorldChannel != null) {
try {
Cast.CastApi.sendMessage(mApiClient,
mHelloWorldChannel.getNamespace(), message).setResultCallback(
new ResultCallback<Status>() {
@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);
}
}
Sending Messages - MainActivity.java
private void sendMessage(String message) {
if (mApiClient != null && mHelloWorldChannel != null) {
try {
Cast.CastApi.sendMessage(mApiClient,
mHelloWorldChannel.getNamespace(), message).setResultCallback(
new ResultCallback<Status>() {
@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);
}
}
Sending Messages - MainActivity.java
private void sendMessage(String message) {
if (mApiClient != null && mHelloWorldChannel != null) {
try {
Cast.CastApi.sendMessage(mApiClient,
mHelloWorldChannel.getNamespace(), message).setResultCallback(
new ResultCallback<Status>() {
@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);
}
}
Sending Messages - MainActivity.java
private void sendMessage(String message) {
if (mApiClient != null && mHelloWorldChannel != null) {
try {
Cast.CastApi.sendMessage(mApiClient,
mHelloWorldChannel.getNamespace(), message).setResultCallback(
new ResultCallback<Status>() {
@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);
}
}
Sending Messages - MainActivity.java
mSendButton = (Button) findViewById(R.id.button_send);
mSendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendMessage(mTextInput.getText().toString());
}
});
Sending Messages - MainActivity.java
mSendButton = (Button) findViewById(R.id.button_send);
mSendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendMessage(mTextInput.getText().toString());
}
});
Demo
Wrap up
Wrap up
●  Initialize via MediaRouter
●  Select Device via MediaRouteSelector
●  Connect via GoogleApiClient
●  Setup Message Bus
●  Send Messages via CastApi through ApiClient
Using the CastCompanionLibrary for Media
Streaming
Getting Started
●  Checkout CastCompanionLibrary from Github
○  https://github.com/googlecast/CastCompanionLibrary-android
●  Compile AAR file
○  ./gradlew build
●  copy compiled AAR to Project
○  rename to CastCompanionLibrary-2.6.aar
○  add repository flat dir to build.gradle
○  compile 'com.google.sample.castcompanionlibrary:CastCompanionLibrary:2.6@aar'
Cast Companion - build.gradle
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
...
compile 'com.android.support:mediarouter-v7:23.1.0'
compile 'com.google.android.gms:play-services-cast:8.3.0'
companionCompile 'com.google.sample.castcompanionlibrary:CastCompanionLibrary:2.6@aar'
}
Cast Companion - AndroidManifest.xml
<activity
android:name="com.google.android.libraries.cast.companionlibrary.cast.player.VideoCastControllerActivity"
android:theme="@style/AppTheme.NoActionBar" />
Cast Companion - MainActivity.java
private VideoCastManager mCastManager;
private VideoCastConsumer mCastConsumer = new VideoCastConsumerImpl() {};
Cast Companion - MainActivity.java
@Override
protected void onResume() {
Log.d(TAG, "onResume() was called");
mCastManager = VideoCastManager.getInstance();
mCastManager.addVideoCastConsumer(mCastConsumer);
mCastManager.incrementUiCounter();
super.onResume();
}
Cast Companion - MainActivity.java
private void initCast() {
// initialize VideoCastManager
VideoCastManager.
initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null).
setVolumeStep(VOLUME_INCREMENT).
enableFeatures(VideoCastManager.FEATURE_NOTIFICATION |
VideoCastManager.FEATURE_LOCKSCREEN |
VideoCastManager.FEATURE_WIFI_RECONNECT |
VideoCastManager.FEATURE_AUTO_RECONNECT |
VideoCastManager.FEATURE_CAPTIONS_PREFERENCE |
VideoCastManager.FEATURE_DEBUGGING);
}
Cast Companion - MainActivity.java
private void initCast() {
// initialize VideoCastManager
VideoCastManager.
initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null).
setVolumeStep(VOLUME_INCREMENT).
enableFeatures(VideoCastManager.FEATURE_NOTIFICATION |
VideoCastManager.FEATURE_LOCKSCREEN |
VideoCastManager.FEATURE_WIFI_RECONNECT |
VideoCastManager.FEATURE_AUTO_RECONNECT |
VideoCastManager.FEATURE_CAPTIONS_PREFERENCE |
VideoCastManager.FEATURE_DEBUGGING);
}
The Cast Controller Activity.
Provided By Cast Companion Library
Cast Companion - MainActivity.java
private void initCast() {
// initialize VideoCastManager
VideoCastManager.
initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null).
setVolumeStep(VOLUME_INCREMENT).
enableFeatures(VideoCastManager.FEATURE_NOTIFICATION |
VideoCastManager.FEATURE_LOCKSCREEN |
VideoCastManager.FEATURE_WIFI_RECONNECT |
VideoCastManager.FEATURE_AUTO_RECONNECT |
VideoCastManager.FEATURE_CAPTIONS_PREFERENCE |
VideoCastManager.FEATURE_DEBUGGING);
}
Custom Namespace Like Message Channel from
Previous Example
Cast Companion - MainActivity.java
private void initCast() {
// initialize VideoCastManager
VideoCastManager.
initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null).
setVolumeStep(VOLUME_INCREMENT).
enableFeatures(VideoCastManager.FEATURE_NOTIFICATION |
VideoCastManager.FEATURE_LOCKSCREEN |
VideoCastManager.FEATURE_WIFI_RECONNECT |
VideoCastManager.FEATURE_AUTO_RECONNECT |
VideoCastManager.FEATURE_CAPTIONS_PREFERENCE |
VideoCastManager.FEATURE_DEBUGGING);
}
Cast Companion - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
mCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item);
return true;
}
Cast Companion - MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
mCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item);
return true;
}
Cast Companion - MainActivity.java
private void loadRemoteMedia(int position, MediaInfo media, boolean autoPlay) {
mCastManager.startVideoCastControllerActivity(this, media, position, autoPlay);
}
Cast Companion - MainActivity.java
mCastButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaMetadata metadata = new MediaMetadata();
MediaInfo media = new MediaInfo
.Builder(mTextVideoUrl.getText().toString())
.setContentType("video/mp4")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metadata)
.setStreamDuration(596)
.build();
loadRemoteMedia(0, media, true);
}
});
Cast Companion - MainActivity.java
mCastButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaMetadata metadata = new MediaMetadata();
MediaInfo media = new MediaInfo
.Builder(mTextVideoUrl.getText().toString())
.setContentType("video/mp4")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metadata)
.setStreamDuration(596)
.build();
loadRemoteMedia(0, media, true);
}
});
The Url to our Video
e.g. .mp4 file
Cast Companion - MainActivity.java
mCastButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaMetadata metadata = new MediaMetadata();
MediaInfo media = new MediaInfo
.Builder(mTextVideoUrl.getText().toString())
.setContentType("video/mp4")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metadata)
.setStreamDuration(596)
.build();
loadRemoteMedia(0, media, true);
}
});
Required.
Contains Metadata like Studio, Production Year, etc.
Cast Companion - MainActivity.java
mCastButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaMetadata metadata = new MediaMetadata();
MediaInfo media = new MediaInfo
.Builder(mTextVideoUrl.getText().toString())
.setContentType("video/mp4")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metadata)
.setStreamDuration(596)
.build();
loadRemoteMedia(0, media, true);
}
});

Más contenido relacionado

La actualidad más candente

Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Alfredo Morresi
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in AndroidRobert Cooper
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserDan Jenkins
 
Demystifying Android's Bluetooth Low Energy at MCE^3 Conf
Demystifying Android's Bluetooth Low Energy at MCE^3 ConfDemystifying Android's Bluetooth Low Energy at MCE^3 Conf
Demystifying Android's Bluetooth Low Energy at MCE^3 ConfPawel Urban
 
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack TorontoGetting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack TorontoDan Jenkins
 
MCE^3 - Dariusz Seweryn, Paweł Urban - Demystifying Android's Bluetooth Low ...
MCE^3 - Dariusz Seweryn, Paweł Urban -  Demystifying Android's Bluetooth Low ...MCE^3 - Dariusz Seweryn, Paweł Urban -  Demystifying Android's Bluetooth Low ...
MCE^3 - Dariusz Seweryn, Paweł Urban - Demystifying Android's Bluetooth Low ...PROIDEA
 
Google I/O 2021 Recap
Google I/O 2021 RecapGoogle I/O 2021 Recap
Google I/O 2021 Recapfurusin
 
Getting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackferenceGetting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackferenceDan Jenkins
 
Android Sliding Menu dengan Navigation Drawer
Android Sliding Menu dengan Navigation DrawerAndroid Sliding Menu dengan Navigation Drawer
Android Sliding Menu dengan Navigation DrawerAgus Haryanto
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developersPavel Lahoda
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon Berlin
 
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.UA Mobile
 
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv Startup Club
 
I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)Katsumi Kishikawa
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserDan Jenkins
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 

La actualidad más candente (20)

Introduction to android
Introduction to androidIntroduction to android
Introduction to android
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 
Introduction toandroid
Introduction toandroidIntroduction toandroid
Introduction toandroid
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
 
Demystifying Android's Bluetooth Low Energy at MCE^3 Conf
Demystifying Android's Bluetooth Low Energy at MCE^3 ConfDemystifying Android's Bluetooth Low Energy at MCE^3 Conf
Demystifying Android's Bluetooth Low Energy at MCE^3 Conf
 
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack TorontoGetting Physical with Web Bluetooth in the Browser Full Stack Toronto
Getting Physical with Web Bluetooth in the Browser Full Stack Toronto
 
MCE^3 - Dariusz Seweryn, Paweł Urban - Demystifying Android's Bluetooth Low ...
MCE^3 - Dariusz Seweryn, Paweł Urban -  Demystifying Android's Bluetooth Low ...MCE^3 - Dariusz Seweryn, Paweł Urban -  Demystifying Android's Bluetooth Low ...
MCE^3 - Dariusz Seweryn, Paweł Urban - Demystifying Android's Bluetooth Low ...
 
Google I/O 2021 Recap
Google I/O 2021 RecapGoogle I/O 2021 Recap
Google I/O 2021 Recap
 
Getting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackferenceGetting physical with web bluetooth in the browser hackference
Getting physical with web bluetooth in the browser hackference
 
Android Sliding Menu dengan Navigation Drawer
Android Sliding Menu dengan Navigation DrawerAndroid Sliding Menu dengan Navigation Drawer
Android Sliding Menu dengan Navigation Drawer
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
 
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
 
I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 
Getting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browserGetting physical with web bluetooth in the browser
Getting physical with web bluetooth in the browser
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Parse Advanced
Parse AdvancedParse Advanced
Parse Advanced
 

Destacado

Google Cast for iOS and Android using Xamarin
Google Cast for iOS and Android using XamarinGoogle Cast for iOS and Android using Xamarin
Google Cast for iOS and Android using XamarinPeter Major
 
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...BeMyApp
 
Developing for Chromecast on Android
Developing for Chromecast on AndroidDeveloping for Chromecast on Android
Developing for Chromecast on AndroidKurt Mbanje
 
Developing for Chromecast on Android
Developing for Chromecast on AndroidDeveloping for Chromecast on Android
Developing for Chromecast on AndroidKurt Mbanje
 
Supporting multiple screens on android
Supporting multiple screens on androidSupporting multiple screens on android
Supporting multiple screens on androidLi SUN
 
Second-Screen Support in Android 4.2
Second-Screen Support in Android 4.2Second-Screen Support in Android 4.2
Second-Screen Support in Android 4.2CommonsWare
 
Secondary Screen Support Using DisplayManager
Secondary Screen Support Using DisplayManagerSecondary Screen Support Using DisplayManager
Secondary Screen Support Using DisplayManagerCommonsWare
 
Using the Presentation API and external screens on Android
Using the Presentation API and external screens on AndroidUsing the Presentation API and external screens on Android
Using the Presentation API and external screens on AndroidXavier Hallade
 

Destacado (8)

Google Cast for iOS and Android using Xamarin
Google Cast for iOS and Android using XamarinGoogle Cast for iOS and Android using Xamarin
Google Cast for iOS and Android using Xamarin
 
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...
[Android Codefest] Using the Second-Screen API & Intel® Wireless Display From...
 
Developing for Chromecast on Android
Developing for Chromecast on AndroidDeveloping for Chromecast on Android
Developing for Chromecast on Android
 
Developing for Chromecast on Android
Developing for Chromecast on AndroidDeveloping for Chromecast on Android
Developing for Chromecast on Android
 
Supporting multiple screens on android
Supporting multiple screens on androidSupporting multiple screens on android
Supporting multiple screens on android
 
Second-Screen Support in Android 4.2
Second-Screen Support in Android 4.2Second-Screen Support in Android 4.2
Second-Screen Support in Android 4.2
 
Secondary Screen Support Using DisplayManager
Secondary Screen Support Using DisplayManagerSecondary Screen Support Using DisplayManager
Secondary Screen Support Using DisplayManager
 
Using the Presentation API and external screens on Android
Using the Presentation API and external screens on AndroidUsing the Presentation API and external screens on Android
Using the Presentation API and external screens on Android
 

Similar a Google Cast with Android: How to Implement Google Cast into Android Apps

Desenvolver para Chromecast
Desenvolver para ChromecastDesenvolver para Chromecast
Desenvolver para ChromecastPedro Veloso
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Mario Jorge Pereira
 
android level 3
android level 3android level 3
android level 3DevMix
 
Android activity, service, and broadcast recievers
Android activity, service, and broadcast recieversAndroid activity, service, and broadcast recievers
Android activity, service, and broadcast recieversUtkarsh Mankad
 
Android Workshop
Android WorkshopAndroid Workshop
Android WorkshopJunda Ong
 
Beginning Native Android Apps
Beginning Native Android AppsBeginning Native Android Apps
Beginning Native Android AppsGil Irizarry
 
Android app development basics
Android app development basicsAndroid app development basics
Android app development basicsAnton Narusberg
 
21 android2 updated
21 android2 updated21 android2 updated
21 android2 updatedGhanaGTUG
 
07_UIAndroid.pdf
07_UIAndroid.pdf07_UIAndroid.pdf
07_UIAndroid.pdfImranS18
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QATed Drake
 
Android TV: Building apps with Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback LibraryAndroid TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with Google’s Leanback LibraryJoe Birch
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...mharkus
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesMichael Galpin
 
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...viWave Study Group - Introduction to Google Android Development - Chapter 23 ...
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...Ted Chien
 
Android appwidget
Android appwidgetAndroid appwidget
Android appwidgetKrazy Koder
 
Introduction to Android Programming
Introduction to Android ProgrammingIntroduction to Android Programming
Introduction to Android ProgrammingRaveendra R
 

Similar a Google Cast with Android: How to Implement Google Cast into Android Apps (20)

Desenvolver para Chromecast
Desenvolver para ChromecastDesenvolver para Chromecast
Desenvolver para Chromecast
 
Android programming basics
Android programming basicsAndroid programming basics
Android programming basics
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015
 
android level 3
android level 3android level 3
android level 3
 
Android activity, service, and broadcast recievers
Android activity, service, and broadcast recieversAndroid activity, service, and broadcast recievers
Android activity, service, and broadcast recievers
 
Android Workshop
Android WorkshopAndroid Workshop
Android Workshop
 
Beginning Native Android Apps
Beginning Native Android AppsBeginning Native Android Apps
Beginning Native Android Apps
 
Android app development basics
Android app development basicsAndroid app development basics
Android app development basics
 
21 android2 updated
21 android2 updated21 android2 updated
21 android2 updated
 
07_UIAndroid.pdf
07_UIAndroid.pdf07_UIAndroid.pdf
07_UIAndroid.pdf
 
Compose In Practice
Compose In PracticeCompose In Practice
Compose In Practice
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QA
 
Android TV: Building apps with Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback LibraryAndroid TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with Google’s Leanback Library
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
Android 3
Android 3Android 3
Android 3
 
Mini curso Android
Mini curso AndroidMini curso Android
Mini curso Android
 
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...viWave Study Group - Introduction to Google Android Development - Chapter 23 ...
viWave Study Group - Introduction to Google Android Development - Chapter 23 ...
 
Android appwidget
Android appwidgetAndroid appwidget
Android appwidget
 
Introduction to Android Programming
Introduction to Android ProgrammingIntroduction to Android Programming
Introduction to Android Programming
 

Último

Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxAsutosh Ranjan
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxhumanexperienceaaa
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxJoão Esperancinha
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 
Processing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptxProcessing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptxpranjaldaimarysona
 
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...ranjana rawat
 
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝soniya singh
 
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Call Girls in Nagpur High Profile
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...Soham Mondal
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...RajaP95
 
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130Suhani Kapoor
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...Call Girls in Nagpur High Profile
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Dr.Costas Sachpazis
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130Suhani Kapoor
 

Último (20)

Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
Processing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptxProcessing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptx
 
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...
(TARA) Talegaon Dabhade Call Girls Just Call 7001035870 [ Cash on Delivery ] ...
 
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Narela Delhi reach out to us at 🔝8264348440🔝
 
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
 
Roadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and RoutesRoadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and Routes
 
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
 
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
 

Google Cast with Android: How to Implement Google Cast into Android Apps

  • 1. Google Cast with Android How to Implement Google Cast into Android Apps +Angelo Rüggeberg @s3xy4ngyc
  • 2. agenda -  Introduction to Google Cast -  Connecting an Android App to an Cast App -  Launching the Cast App -  Interacting with the Cast App -  using the CastCompanionLibrary for Media
  • 4.
  • 5. Biggest, most beautiful screen in the house...
  • 6. Your app on the TV!
  • 7. Simple to get started with the SDK
  • 15. Your app is ‘The Sender’
  • 17. Receiver app runs on Cast receiving device
  • 18. Cast SDK app looks for Cast devices
  • 19. Cast icon shown on discovery of Cast devices
  • 22. developers.google.com/cast/ docs/ux_guidelines ●  Selecting Cast Device ●  Pausing & Scrubbing ●  Visual Consistency
  • 28. Leader Board 1st Scotty 145 2nd Andrea 109 3rd Ralph 94
  • 29.
  • 31. Connecting an Android App to an Cast App
  • 32. Environment: ●  Real Device ○  with Google Play Services Installed ●  Cast Device ○  e.g. Chromecast Prequesites Dependencies: play-services-cast Handles Connection to Cast 'com.google.android.gms:play-services-cast:8.3.0' support-media-router Button to Connect to Cast 'com.android.support:mediarouter-v7:23.1.0'
  • 33. Dependencies - build.gradle dependencies { compile 'com.android.support:mediarouter-v7:23.1.0' compile 'com.google.android.gms:play-services-cast:8.3.0' }
  • 34. Permissions - Manifest.xml <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  • 35. Adding Media Route Button via Menu <?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>
  • 36. Adding Media Route Button via Menu <?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>
  • 37. Adding Media Route Button to an Layout <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.v7.app.MediaRouteButton android:id="@+id/media_route_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:mediaRouteTypes="user" /> … </RelativeLayout>
  • 38. Adding Media Route Button to an Layout <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.v7.app.MediaRouteButton android:id="@+id/media_route_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:mediaRouteTypes="user" /> … </RelativeLayout>
  • 39. Adding Media Route Button to an Layout <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.v7.app.MediaRouteButton android:id="@+id/media_route_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:mediaRouteTypes="user" /> … </RelativeLayout>
  • 40. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice;
  • 41. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice; The Button added To the Layout
  • 42. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice; The Media Router. This handles the Connection to our Cast Device
  • 43. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice; The Route Selector. This is the Configuration for our Connection e.g the Device to Interact with
  • 44. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice; The Router Callbacks. These Callbacks are used to Notify the Application on Select and Deselction of an Device Route and enables us to react to these events e.g by printing the Connected Device to the User.
  • 45. Fields - MainActivity.java private MediaRouteButton mMediaRouteButton; private MediaRouter mMediaRouter; private MediaRouteSelector mMediaRouteSelector; private MediaRouter.Callback mMediaRouterCallback; private CastDevice mSelectedDevice; The Cast Device we are Connected to. It contains Informations like Device Name, Model, Capabilities, etc.
  • 46. Initializing - MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mConnectionStatus = (TextView) findViewById(R.id.text_connection); mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button); initCast(); }
  • 47. Initializing - MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mConnectionStatus = (TextView) findViewById(R.id.text_connection); mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button); initCast(); }
  • 48. Initializing - MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mConnectionStatus = (TextView) findViewById(R.id.text_connection); mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button); initCast(); }
  • 49. Initializing - MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mConnectionStatus = (TextView) findViewById(R.id.text_connection); mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button); initCast(); }
  • 50. Initializing - MainActivity.java private void initCast() { // Configure Cast device discovery mMediaRouter = MediaRouter.getInstance(getApplicationContext()); }
  • 51. Initializing - MainActivity.java private void initCast() { // Configure Cast device discovery mMediaRouter = MediaRouter.getInstance(getApplicationContext()); mMediaRouteSelector = new MediaRouteSelector.Builder() .addControlCategory( CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id))) .build(); }
  • 52. Initializing - MainActivity.java private void initCast() { // Configure Cast device discovery mMediaRouter = MediaRouter.getInstance(getApplicationContext()); mMediaRouteSelector = new MediaRouteSelector.Builder() .addControlCategory( CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id))) .build(); } The Cast Application ID. E.g “794B7BBF” (Cast Sample Helloworld)
  • 53. Initializing - MainActivity.java private void initCast() { // Configure Cast device discovery mMediaRouter = MediaRouter.getInstance(getApplicationContext()); mMediaRouteSelector = new MediaRouteSelector.Builder() .addControlCategory(CastMediaControlIntent.categoryForCast(getResources() .getString(R.string.app_id))) .build(); // Set the MediaRouteButton selector for device discovery. mMediaRouteButton.setRouteSelector(mMediaRouteSelector); }
  • 54. Initializing - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat .getActionProvider(mediaRouteMenuItem); // Set the MediaRouteActionProvider selector for device discovery. mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector); return true; }
  • 55. Initializing - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat .getActionProvider(mediaRouteMenuItem); // Set the MediaRouteActionProvider selector for device discovery. mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector); return true; }
  • 56. Initializing - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat .getActionProvider(mediaRouteMenuItem); // Set the MediaRouteActionProvider selector for device discovery. mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector); return true; }
  • 57. Initializing - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat .getActionProvider(mediaRouteMenuItem); // Set the MediaRouteActionProvider selector for device discovery. mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector); return true; }
  • 58. Adding Callbacks - MainActivity.java private void initCast() { // Configure Cast device discovery mMediaRouter = MediaRouter.getInstance(getApplicationContext()); mMediaRouteSelector = new MediaRouteSelector.Builder() .addControlCategory(CastMediaControlIntent.categoryForCast(getResources() .getString(R.string.app_id))) .build(); // Set the MediaRouteButton selector for device discovery. mMediaRouteButton.setRouteSelector(mMediaRouteSelector); mMediaRouterCallback = new MyMediaRouterCallback(); }
  • 59. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } }
  • 60. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } }
  • 61. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } } Called after we Selected an Cast Device we want to Connect with. This does not mean we are Connected to the Cast Application yet!
  • 62. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } } Called after we Decided to Disconnect from an Cast Device. This does not mean we are Disconnected from the Application yet!
  • 63. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } }
  • 64. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } }
  • 65. Adding Callbacks - MainActivity.java private class MyMediaRouterCallback extends MediaRouter.Callback { @Override public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) { // Handle the user route selection. mSelectedDevice = CastDevice.getFromBundle(info.getExtras()); mConnectionStatus.setText("Connected to: " + mSelectedDevice.getFriendlyName()); } @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) { mSelectedDevice = null; mConnectionStatus.setText("Not Connected"); } }
  • 66. Starting Discovery - MainActivity.java @Override protected void onStart() { super.onStart(); // Start media router discovery mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); } @Override protected void onStop() { // End media router discovery mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }
  • 67. Starting Discovery - MainActivity.java @Override protected void onStart() { super.onStart(); // Start media router discovery mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); } @Override protected void onStop() { // End media router discovery mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }
  • 68. Starting Discovery - MainActivity.java @Override protected void onStart() { super.onStart(); // Start media router discovery mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); } @Override protected void onStop() { // End media router discovery mMediaRouter.removeCallback(mMediaRouterCallback); super.onStop(); }
  • 69. Demo
  • 70. Launching the Cast Application
  • 71. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId;
  • 72. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId; The Api Client is used to Interact with The Chromecast e.g. Sending Messages
  • 73. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId; Our Callbacks to Notify us about Connection Events e.g. disconnection
  • 74. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId; The Connection Callbacks. e.G. we get disconnected due to application errors
  • 75. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId; Our Callback if the connection Fails
  • 76. New Fields - MainActivity.java private GoogleApiClient mApiClient; private Cast.Listener mCastListener; private ConnectionCallbacks mConnectionCallbacks; private ConnectionFailedListener mConnectionFailedListener; private boolean mApplicationStarted; private boolean mWaitingForReconnect; private String mSessionId; We keep Some Information for our Application stored in these Fields
  • 77. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { @Override public void onApplicationDisconnected(int errorCode) { Log.d(TAG, "application has stopped"); teardown(true); } }; }
  • 78. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); }
  • 79. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); }
  • 80. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); }
  • 81. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); mApiClient = new GoogleApiClient.Builder(this) .addApi(Cast.API, apiOptionsBuilder.build()) .addConnectionCallbacks(mConnectionCallbacks) .addOnConnectionFailedListener(mConnectionFailedListener) .build(); }
  • 82. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); mApiClient = new GoogleApiClient.Builder(this) .addApi(Cast.API, apiOptionsBuilder.build()) .addConnectionCallbacks(mConnectionCallbacks) .addOnConnectionFailedListener(mConnectionFailedListener) .build(); }
  • 83. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); mApiClient = new GoogleApiClient.Builder(this) .addApi(Cast.API, apiOptionsBuilder.build()) .addConnectionCallbacks(mConnectionCallbacks) .addOnConnectionFailedListener(mConnectionFailedListener) .build(); }
  • 84. Launching the Cast Application - MainActivity.java private void launchReceiver() { mCastListener = new Cast.Listener() { … }; mConnectionCallbacks = new ConnectionCallbacks(); mConnectionFailedListener = new ConnectionFailedListener(); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(mSelectedDevice, mCastListener); mApiClient = new GoogleApiClient.Builder(this) .addApi(Cast.API, apiOptionsBuilder.build()) .addConnectionCallbacks(mConnectionCallbacks) .addOnConnectionFailedListener(mConnectionFailedListener) .build(); mApiClient.connect(); }
  • 85. Launching the Cast Application - MainActivity.java private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks { @Override public void onConnected(Bundle connectionHint) { ... // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) .setResultCallback( new ResultCallback<Cast.ApplicationConnectionResult>() { @Override public void onResult(Cast.ApplicationConnectionResult result) { … } }
  • 86. Launching the Cast Application - MainActivity.java private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks { @Override public void onConnected(Bundle connectionHint) { ... // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) .setResultCallback( new ResultCallback<Cast.ApplicationConnectionResult>() { @Override public void onResult(Cast.ApplicationConnectionResult result) { … } }
  • 87. Launching the Cast Application - MainActivity.java Status status = result.getStatus(); if (status.isSuccess()) { ApplicationMetadata applicationMetadata = result .getApplicationMetadata(); mSessionId = result.getSessionId(); mApplicationStarted = true; } else { Log.e(TAG, "application could not launch"); teardown(true); }
  • 88. Launching the Cast Application - MainActivity.java Status status = result.getStatus(); if (status.isSuccess()) { ApplicationMetadata applicationMetadata = result .getApplicationMetadata(); mSessionId = result.getSessionId(); mApplicationStarted = true; } else { Log.e(TAG, "application could not launch"); teardown(true); }
  • 89. Launching the Cast Application - MainActivity.java Status status = result.getStatus(); if (status.isSuccess()) { ApplicationMetadata applicationMetadata = result .getApplicationMetadata(); mSessionId = result.getSessionId(); mApplicationStarted = true; } else { Log.e(TAG, "application could not launch"); teardown(true); }
  • 90. Launching the Cast Application - MainActivity.java Status status = result.getStatus(); if (status.isSuccess()) { ApplicationMetadata applicationMetadata = result .getApplicationMetadata(); mSessionId = result.getSessionId(); mApplicationStarted = true; } else { Log.e(TAG, "application could not launch"); teardown(true); }
  • 91. Launching the Cast Application - MainActivity.java private void teardown(boolean selectDefaultRoute) { if (mApiClient != null) { if (mApplicationStarted) { if (mApiClient.isConnected() || mApiClient.isConnecting()) { Cast.CastApi.stopApplication(mApiClient, mSessionId); mApiClient.disconnect(); } mApplicationStarted = false; } mApiClient = null; } mSelectedDevice = null; mWaitingForReconnect = false; mSessionId = null; }
  • 92. Launching the Cast Application - MainActivity.java private void teardown(boolean selectDefaultRoute) { if (mApiClient != null) { if (mApplicationStarted) { if (mApiClient.isConnected() || mApiClient.isConnecting()) { Cast.CastApi.stopApplication(mApiClient, mSessionId); mApiClient.disconnect(); } mApplicationStarted = false; } mApiClient = null; } mSelectedDevice = null; mWaitingForReconnect = false; mSessionId = null; }
  • 93. Launching the Cast Application - MainActivity.java private void teardown(boolean selectDefaultRoute) { if (mApiClient != null) { if (mApplicationStarted) { if (mApiClient.isConnected() || mApiClient.isConnecting()) { Cast.CastApi.stopApplication(mApiClient, mSessionId); mApiClient.disconnect(); } mApplicationStarted = false; } mApiClient = null; } mSelectedDevice = null; mWaitingForReconnect = false; mSessionId = null; }
  • 94. Launching the Cast Application - MainActivity.java private void teardown(boolean selectDefaultRoute) { if (mApiClient != null) { if (mApplicationStarted) { if (mApiClient.isConnected() || mApiClient.isConnecting()) { Cast.CastApi.stopApplication(mApiClient, mSessionId); mApiClient.disconnect(); } mApplicationStarted = false; } mApiClient = null; } mSelectedDevice = null; mWaitingForReconnect = false; mSessionId = null; }
  • 95. Demo
  • 96. Interacting with the Cast Application
  • 97. Sending Messages - MainActivity.java class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return getString(R.string.namespace); } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { } }
  • 98. Sending Messages - MainActivity.java class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return getString(R.string.namespace); } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { } }
  • 99. Sending Messages - MainActivity.java class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return getString(R.string.namespace); } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { } } Our Custom Namespace. This is defined in our reciever app. e.g. urn:x-cast:com.google.cast.sample.helloworld
  • 100. Sending Messages - MainActivity.java class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return getString(R.string.namespace); } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { } } This gets Triggered when the Reciever Sends Data To our Client. e.g. Updated Scores on Games
  • 101. Sending Messages - MainActivity.java // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) …. // Create the custom message // channel mHelloWorldChannel = new HelloWorldChannel(); try { Cast.CastApi.setMessageReceivedCallbacks( mApiClient, mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
  • 102. Sending Messages - MainActivity.java // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) …. // Create the custom message // channel mHelloWorldChannel = new HelloWorldChannel(); try { Cast.CastApi.setMessageReceivedCallbacks( mApiClient, mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
  • 103. Sending Messages - MainActivity.java // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) …. // Create the custom message // channel mHelloWorldChannel = new HelloWorldChannel(); try { Cast.CastApi.setMessageReceivedCallbacks( mApiClient, mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
  • 104. Sending Messages - MainActivity.java // Launch the receiver app Cast.CastApi.launchApplication(mApiClient, getString(R.string.app_id), false) …. // Create the custom message // channel mHelloWorldChannel = new HelloWorldChannel(); try { Cast.CastApi.setMessageReceivedCallbacks( mApiClient, mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
  • 105. Sending Messages - MainActivity.java private void sendMessage(String message) { if (mApiClient != null && mHelloWorldChannel != null) { try { Cast.CastApi.sendMessage(mApiClient, mHelloWorldChannel.getNamespace(), message).setResultCallback( new ResultCallback<Status>() { @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); } }
  • 106. Sending Messages - MainActivity.java private void sendMessage(String message) { if (mApiClient != null && mHelloWorldChannel != null) { try { Cast.CastApi.sendMessage(mApiClient, mHelloWorldChannel.getNamespace(), message).setResultCallback( new ResultCallback<Status>() { @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); } }
  • 107. Sending Messages - MainActivity.java private void sendMessage(String message) { if (mApiClient != null && mHelloWorldChannel != null) { try { Cast.CastApi.sendMessage(mApiClient, mHelloWorldChannel.getNamespace(), message).setResultCallback( new ResultCallback<Status>() { @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); } }
  • 108. Sending Messages - MainActivity.java private void sendMessage(String message) { if (mApiClient != null && mHelloWorldChannel != null) { try { Cast.CastApi.sendMessage(mApiClient, mHelloWorldChannel.getNamespace(), message).setResultCallback( new ResultCallback<Status>() { @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); } }
  • 109. Sending Messages - MainActivity.java mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendMessage(mTextInput.getText().toString()); } });
  • 110. Sending Messages - MainActivity.java mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendMessage(mTextInput.getText().toString()); } });
  • 111. Demo
  • 113. Wrap up ●  Initialize via MediaRouter ●  Select Device via MediaRouteSelector ●  Connect via GoogleApiClient ●  Setup Message Bus ●  Send Messages via CastApi through ApiClient
  • 114. Using the CastCompanionLibrary for Media Streaming
  • 115. Getting Started ●  Checkout CastCompanionLibrary from Github ○  https://github.com/googlecast/CastCompanionLibrary-android ●  Compile AAR file ○  ./gradlew build ●  copy compiled AAR to Project ○  rename to CastCompanionLibrary-2.6.aar ○  add repository flat dir to build.gradle ○  compile 'com.google.sample.castcompanionlibrary:CastCompanionLibrary:2.6@aar'
  • 116. Cast Companion - build.gradle repositories { flatDir { dirs 'libs' } } dependencies { ... compile 'com.android.support:mediarouter-v7:23.1.0' compile 'com.google.android.gms:play-services-cast:8.3.0' companionCompile 'com.google.sample.castcompanionlibrary:CastCompanionLibrary:2.6@aar' }
  • 117. Cast Companion - AndroidManifest.xml <activity android:name="com.google.android.libraries.cast.companionlibrary.cast.player.VideoCastControllerActivity" android:theme="@style/AppTheme.NoActionBar" />
  • 118. Cast Companion - MainActivity.java private VideoCastManager mCastManager; private VideoCastConsumer mCastConsumer = new VideoCastConsumerImpl() {};
  • 119. Cast Companion - MainActivity.java @Override protected void onResume() { Log.d(TAG, "onResume() was called"); mCastManager = VideoCastManager.getInstance(); mCastManager.addVideoCastConsumer(mCastConsumer); mCastManager.incrementUiCounter(); super.onResume(); }
  • 120. Cast Companion - MainActivity.java private void initCast() { // initialize VideoCastManager VideoCastManager. initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null). setVolumeStep(VOLUME_INCREMENT). enableFeatures(VideoCastManager.FEATURE_NOTIFICATION | VideoCastManager.FEATURE_LOCKSCREEN | VideoCastManager.FEATURE_WIFI_RECONNECT | VideoCastManager.FEATURE_AUTO_RECONNECT | VideoCastManager.FEATURE_CAPTIONS_PREFERENCE | VideoCastManager.FEATURE_DEBUGGING); }
  • 121. Cast Companion - MainActivity.java private void initCast() { // initialize VideoCastManager VideoCastManager. initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null). setVolumeStep(VOLUME_INCREMENT). enableFeatures(VideoCastManager.FEATURE_NOTIFICATION | VideoCastManager.FEATURE_LOCKSCREEN | VideoCastManager.FEATURE_WIFI_RECONNECT | VideoCastManager.FEATURE_AUTO_RECONNECT | VideoCastManager.FEATURE_CAPTIONS_PREFERENCE | VideoCastManager.FEATURE_DEBUGGING); } The Cast Controller Activity. Provided By Cast Companion Library
  • 122. Cast Companion - MainActivity.java private void initCast() { // initialize VideoCastManager VideoCastManager. initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null). setVolumeStep(VOLUME_INCREMENT). enableFeatures(VideoCastManager.FEATURE_NOTIFICATION | VideoCastManager.FEATURE_LOCKSCREEN | VideoCastManager.FEATURE_WIFI_RECONNECT | VideoCastManager.FEATURE_AUTO_RECONNECT | VideoCastManager.FEATURE_CAPTIONS_PREFERENCE | VideoCastManager.FEATURE_DEBUGGING); } Custom Namespace Like Message Channel from Previous Example
  • 123. Cast Companion - MainActivity.java private void initCast() { // initialize VideoCastManager VideoCastManager. initialize(this, getString(R.string.app_id), VideoCastControllerActivity.class, null). setVolumeStep(VOLUME_INCREMENT). enableFeatures(VideoCastManager.FEATURE_NOTIFICATION | VideoCastManager.FEATURE_LOCKSCREEN | VideoCastManager.FEATURE_WIFI_RECONNECT | VideoCastManager.FEATURE_AUTO_RECONNECT | VideoCastManager.FEATURE_CAPTIONS_PREFERENCE | VideoCastManager.FEATURE_DEBUGGING); }
  • 124. Cast Companion - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); mCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item); return true; }
  • 125. Cast Companion - MainActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); mCastManager.addMediaRouterButton(menu, R.id.media_route_menu_item); return true; }
  • 126. Cast Companion - MainActivity.java private void loadRemoteMedia(int position, MediaInfo media, boolean autoPlay) { mCastManager.startVideoCastControllerActivity(this, media, position, autoPlay); }
  • 127. Cast Companion - MainActivity.java mCastButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MediaMetadata metadata = new MediaMetadata(); MediaInfo media = new MediaInfo .Builder(mTextVideoUrl.getText().toString()) .setContentType("video/mp4") .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setMetadata(metadata) .setStreamDuration(596) .build(); loadRemoteMedia(0, media, true); } });
  • 128. Cast Companion - MainActivity.java mCastButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MediaMetadata metadata = new MediaMetadata(); MediaInfo media = new MediaInfo .Builder(mTextVideoUrl.getText().toString()) .setContentType("video/mp4") .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setMetadata(metadata) .setStreamDuration(596) .build(); loadRemoteMedia(0, media, true); } }); The Url to our Video e.g. .mp4 file
  • 129. Cast Companion - MainActivity.java mCastButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MediaMetadata metadata = new MediaMetadata(); MediaInfo media = new MediaInfo .Builder(mTextVideoUrl.getText().toString()) .setContentType("video/mp4") .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setMetadata(metadata) .setStreamDuration(596) .build(); loadRemoteMedia(0, media, true); } }); Required. Contains Metadata like Studio, Production Year, etc.
  • 130. Cast Companion - MainActivity.java mCastButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MediaMetadata metadata = new MediaMetadata(); MediaInfo media = new MediaInfo .Builder(mTextVideoUrl.getText().toString()) .setContentType("video/mp4") .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setMetadata(metadata) .setStreamDuration(596) .build(); loadRemoteMedia(0, media, true); } });