The document discusses how to implement Google Cast into Android apps. It covers connecting an Android app to a Cast receiver app, launching the Cast app, and interacting with the Cast app. It provides code examples for initializing the Cast SDK, adding callbacks to handle Cast device selection and deselection, and starting discovery of Cast devices.
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
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
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'
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.
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");
}
}
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
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);
}
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
113. Wrap up
● Initialize via MediaRouter
● Select Device via MediaRouteSelector
● Connect via GoogleApiClient
● Setup Message Bus
● Send Messages via CastApi through ApiClient
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;
}