SlideShare une entreprise Scribd logo
1  sur  130
Télécharger pour lire hors ligne
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);
}
});

Contenu connexe

Tendances

Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
Droidcon Berlin
 

Tendances (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
 

En vedette

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
Xavier Hallade
 

En vedette (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
 

Similaire à Implementing cast in android

Android activity, service, and broadcast recievers
Android activity, service, and broadcast recieversAndroid activity, service, and broadcast recievers
Android activity, service, and broadcast recievers
Utkarsh Mankad
 
Android app development basics
Android app development basicsAndroid app development basics
Android app development basics
Anton Narusberg
 
Android appwidget
Android appwidgetAndroid appwidget
Android appwidget
Krazy Koder
 

Similaire à Implementing cast in android (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
 

Dernier

Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
Neometrix_Engineering_Pvt_Ltd
 
notes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.pptnotes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.ppt
MsecMca
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
DeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakesDeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakes
MayuraD1
 

Dernier (20)

Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
 
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKARHAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.ppt
 
Double Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torqueDouble Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torque
 
Learn the concepts of Thermodynamics on Magic Marks
Learn the concepts of Thermodynamics on Magic MarksLearn the concepts of Thermodynamics on Magic Marks
Learn the concepts of Thermodynamics on Magic Marks
 
Online food ordering system project report.pdf
Online food ordering system project report.pdfOnline food ordering system project report.pdf
Online food ordering system project report.pdf
 
notes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.pptnotes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.ppt
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptx
 
Engineering Drawing focus on projection of planes
Engineering Drawing focus on projection of planesEngineering Drawing focus on projection of planes
Engineering Drawing focus on projection of planes
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
Online electricity billing project report..pdf
Online electricity billing project report..pdfOnline electricity billing project report..pdf
Online electricity billing project report..pdf
 
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
 
Air Compressor reciprocating single stage
Air Compressor reciprocating single stageAir Compressor reciprocating single stage
Air Compressor reciprocating single stage
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
 
DeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakesDeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakes
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.ppt
 
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptxA CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
 
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best ServiceTamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
 
2016EF22_0 solar project report rooftop projects
2016EF22_0 solar project report rooftop projects2016EF22_0 solar project report rooftop projects
2016EF22_0 solar project report rooftop projects
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 

Implementing cast in android

  • 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); } });