Make your Android app compatible with your Chromecast

Quentin Klein
Nov 16, 2018 · 9 min read

Especially if your app is not a media app. Else it’s not fun.

A little story

If you don’t know where you’ve come from, you don’t know where you’re going
— Maya Angelou

Back to 2013

The first Chromecast was released in 2013 in the US (and 2014 in France).

4 years ago, and it looks like a decade.

From the very first time, Google has designed the cast technology to be open to third party apps.
More, they are providing a SDK to help us interact with it.

But since, IMHO, the technology behind the Chromecast has not been really used.

I mean, technically, you can share whatever you want on your TV screen!
But, most of the time, apps are not compatible (or you don’t know they are).

The first version of the SDK was made to cast whatever you want, but the last version is clearly made for media casting (music, video, photo).

Hey, it’s meant to be used on a TV isn’t it?

With that said, I would like to see more games, more apps, more things compatible with this old friend.

So how can we do that?

First, How does it work?

We need to understand how the cast technology works.

It is important to understand that it does not read messages directly from your app (or your chrome tab) but from a website.

The cast technology explained by my incredible skills in drawing

When you “Cast on…” from a sender app (ex. an Android app), you ask the cast device to open a specific web app, called the receiver app.

This receiver app is hosted online. Once loaded by the cast device, you can communicate between them by some sort of sockets.

So what does that mean?

First, you can’t stream tons of data, or the latency will make it impossible to use the app.
Then, you’ll have to do a web app and host it somewhere. (The receiver app).
Finally, you’ll have to establish communication between the receiver app and your app (the sender app).


Le‘t’s do this.

The steps to develop a cast application are:

  1. [Setup] Register a dev account
  2. [Setup] Link you Chromecast to your dev account
  3. [Setup] Declare the app
  4. [Build] Create the receiver
  5. [Build] Create the sender

Register a dev account

You’ll need:
- A Google Account
- A credit card 💰

In order to develop with the cast SDK, you will have to register your account and… give Google some 💰.

As I’m writing these lines, it is a one time $5 registration fee.

Then, you will access the Google Cast SDK Developer Console

Cast console

As you can see, there are 2 categories:
- the Applications
- and the Cast Receiver Devices.

The Applications are declared when you develop and publish your receiver apps.

The Cast Receiver Devices are the declared devices with the developer mode on them. It is our next step.


Link you Chromecast to your dev account

You’ll need:
- A Registered Google Cast Account
- A Chromecast

Click on “ADD NEW DEVICE” .
A prompt will ask you the Serial Number of the device.

A particular note to the UX here, if the device is plugged, you can connect the console to the device and hear it from the TV 👍

The description is for you, no impact, but if you add 3 or 4 devices, sounds like a good idea to have a human readable name in mind.

Once it is done, we can ask for the credentials to build our app.


Declare the app

You’ll need:
- A Registered Google Cast Account
- A web hosting place (with a public url)

Click on ADD NEW APPLICATION.

Now, you’ll have to choose the kind of application you want.

Right now there are 3 types (and this is funny)

So, let’s use the Custom Receiver, give it a name and a Receiver Application URL (the public url where will host our receiver app).

Remember, the receiver app is just a web app hosted somewhere.
You can host it yourself or use some cloud hosting.
But, it needs to be reachable from the Internet.

And you’re done, note the Application ID you’ll need it bellow, then, click on the Edit link near the newly created app.

Set the app id in the package name section

Now, you have to provide the packagename/applicationId (old said package name) that will be able to cast to the app.
Just put anything you want, but remember, you’ll deploy your app with this packagename/applicationId so make sure it is not already in use.

That’s it. We’re good for the app declaration. Save it and close the tab.


Create the receiver

You’ll need:
- Your favorite (web?) editor

Let’s do a very simple receiver with the CAF SDK

As defined by Google, a receiver:

- Provides an interface to display the app’s content on the TV.
- Handles messages from the sender application to control content on the receiver device.
- Handles custom messages from the sender application that are application-specific.
https://developers.google.com/cast/docs/caf_receiver_overview

So basically, it handles everything that should be displayed on the screen.

How to use it? Just create an index.html and fill it with

The receiver app index.html

What’s in there ?

  1. [L13] The main instance of the CAF receiver is the CastReceiverContext.
    It manages “the cast session, senders, sending custom messages, and global system events”.
    It replaces the CastReceiverManager from the v2
  2. [L14] An object that will contains our options. (Like the namespaces, timeouts etc)
  3. [L15] In our app (sender and receiver), we will send/receive messages with a custom namespace. (A namespace is a sort of specific named channel).
    For the demo, we will use only one namespace.
    The namespace is defined by you. You can use thepackagename/applicationId you provided for your app, it’s a common thing to set urn:x-cast:applicationId if there is a single channel.
  4. [L17~18] Define the custom namespace we will use and that it communicates in JSON.
    As you can see, you can use way more than one namespace.
    This is used to send data back to the senders apps. See the custom message bus section. (we wont do it in the example).
  5. [L20~26] Here, we create a custom listener for our namesapce, the first parameter is the channel, the second is the listener.
    Even if the method name is addCustomMessageListener you can only set 1 listener per namespace.
    This listener will be triggered when the sender app will send a message in the channel. The message itself will be passed in the customEvent parameter.
    The given event contains data like the senderId and the message content.
  6. [L28] Start the application.
    Be aware that the options are not updatable once the app is started, so make sure you’ve declared all of them before.

Create the sender app

You’ll need:
- Android Studio
- The Application ID of the app you have registered in the cast dev console.

Everything bellow is explained in the official doc:

With that said, let’s make a simple Android app.
Follow the steps of Android Studio to create an app (and when you have to specify the packagename/applicationId , give the same you gave in the steps above).

In the app’s build.gradle , add the Cast dependencies ¹.

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:mediarouter-v7:28.0.0'
implementation 'com.google.android.gms:play-services-cast-framework:16.1.0
See the dependencies (and the packagename/applicationId)

Our sender app is made of 2 things:
- an OptionsProvider to help the framework with the receiver apps to cast.
- an Activity that will manage the communication and actions.

First, the OptionsProvider
Create a class CastOptionsProvider that implements OptionsProvider, we will set this class in the meta in the AndroidManifest section.

The CastOptionsProvider implementation

The receiver_id is a string defined in our strings.xml file. It contains the Application ID you were given when you declared the app in step 1.

And add it in the manifest

Declaration of the cast provider in the AndroidManifest.

Once it is done, let’s create a basic Activity that will do 3 things:

  • Display the cast button.
  • Connect to the cast device.
  • Send messages.

Here we go

The MainActivity, dunno why the coloration is so bad.

Let’s explore the content ?

  1. [L15] castSession represents the session that will be running when the cast will be set up.
  2. [L16] castContext is the context that will manage the sessions.
  3. [L17] The namespace for the messages, remember the one we used in the receiver app, for this case it is urn:x-cast:com.github.quentin7b.estimateit
  4. [L19~40] This is an implementation of the SessionManagerListener<CastSession> class.
    In order to cleanup the code I’ve made an EstimateSessionManagerListener interface that overrides the other methods.
    Here, we manage our castSession item’s life, the methods are triggered by the cast SDK when we are connected to a cast device, when the connection is stopped or when it is resumed.
    By doing that we can re-assign our castSession and manage the state of the cast button in the toolbar.
  5. [L43~52] onCreate Here set a basic layout with one button. When this button is clicked, we send a message with the castSession instance using the sendMessage method.
    This method needs the namespace to use and the message to send (a string).
    For the example, we will send a basic integer between 1 and 5 as the message.
  6. [L54~60] onCreateOptionsMenu In the method, you can focus on the line 57/58. This uses the item defined in the menu as the cast button and listen s to it to trigger the SDK when clicked. The menu should have a cast button.
  7. [L62~76] onResume here, we set the listener of our castContext sessionManager , by doing so, the SDK will trigger the sessionManagerListener when the connection to the cast device is done and when anything happen during the session.
    Finally, if there is already a session running, we affect it to our castSession property.
  8. [L78~87] onPause to prevent any trigger when the app is paused, we do like we would do with a broadcast receiver or any callback, we unset the sessionManagerListener from the sessionManager
  9. [L94~96] cleanup this method is triggered when a session ends or when the activity is destroyed. We reset the castSession to null to prevent leaks

Note that if you want to communicate from the receiver app to the sender app, this is possible by calling the setMessageReceivedCallbacks(namespace: String, callback: Cast.MessageReceivedCallback) method.
Add it in the onSessionStart callback from our sessionManagerListener property.
In the end, make sure to call removeMessageReceivedCallbacks(namespace: String) in the cleanup method to prevent leaks.

Declare the Activity in the manifest, run it, here you go!


Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade