Android TV: Best practices for engaging Apps
How to customize your app’s look and feel and integrate with Android TV features.
Creating a great Android TV app is about getting the basics right, customizing the Leanback library to get the look and feel you want, integrating with Android TV features so people can discover and control your content, and, of course, delivering great content. The latter I’ll leave you to figure out, but for the first 3, this post will get you heading in the right direction. To kick off I want to briefly look at how technology is changing the home and living room.
The modern home and living room
Technology has changed how we interact with the home. Here at Google, we believe that the next leap forward in technology for the home will come from the intersection of hardware, software, and AI. We want people’s homes to be smarter, more helpful, and work for them.
This vision centers around Google Assistant, through its ability to bring together search and media contact points. And when we’re talking about media, there is no better place to consume media than the biggest screen in the home: the TV. Android TV is Google’s TV platform that brings media, games, and music together in one place.
Android TV is seeing great momentum: 7 of the 10 top smart TV manufacturers are shipping TVs with Android TV and over 160 pay TV operators are powering set top boxes with Android TV. This momentum extends to developers as well: there are around 7,000 apps on Google Play for Android TV, over 1,000 of which are from streaming content providers.
What makes an Android app an Android TV app?
Being Android means that you can reuse all of your skills as an Android developer to create an Android TV app, but what makes an Android app a TV app?
I’m going to start with the basics of the manifest file. Some of this may seem really basic but it is missed by many apps.
First, you declare that you won’t be using a touch screen because people interact with their TVs through the remote control.
Next, you declare that the app uses Leanback. This doesn’t specifically refer to the Leanback library: Leanback is a generic term used to define the experience of watching TV and experience where someone uses a device at a distance, in a Leanback position. Using this ensures that the app will only go on TV Google Play Store and not on any other surface like mobile, tablet, etc.
Now you move on to declare the app’s banner.
Before concluding by declaring the Android TV intent, which is not the main intent.
Your app’s banner is how people find it in the Android TV interface. Following best practices, your app’s banner should look something like this:
However, we often see incorrect banners. A common mistake is using the same icon as the mobile app — typically a 512×512-pixel icon in the drawable-xhdpi folder — resulting in a scaled-down icon placed inside a dark rectangle.
The correct approach is to provide a 320×180-pixel icon in the /res/drawable-xhdpi folder. If you provide a banner larger than that, it doesn’t matter in which folder you put it; it’s not going to appear correctly.
Remember that your banner is used as your app’s representation elsewhere too, such as in the Play Next channel, so getting it right is important.
Google Play Store publication
You will want your app published in the Google Play Store for Android TV section. To do this, when submitting your app, in the Pricing & distribution section make sure you check the Distribute your app on Android TV.
We ask you to explicitly elect to distribute your app on Android TV to make sure that you’ve given careful consideration to how your app behaves on the big screen instead of simply detecting that an app has the leanback feature declared. For instance, some hybrid or multi-platform development tools simply enable this feature. However, apps created in these environments may never be tested for TV so they won’t necessarily work correctly on a TV.
The Leanback library is a set of high-level widgets that conform to the material design specs and provide a great experience when people view an app on a TV.
The widgets include those for the home screen — which contains, for example, channels (rows) and a navigation drawer — widgets for content details, and many others for different situations.
There are two principal ways that the Leanback library can be customized for use in your app: change the colors and dimensions values or provide custom presenters.
Colors and dimensions
To illustrate how you can customize Leanback library content, let’s take the BrowseSupportFragment. This fragment is used in the home screen of many apps to show sidebar navigation and the channels of content. The fragment has methods and various properties in which you can modify the colors and dimensions, properties such as padding, title styles, and row styles.
Similarly the navigation drawer, each of the individual cards, and so on have properties and methods that allow you to modify its appearance.
The Leanback library is based on the Model View Pattern (MVP) and many of its widgets enable you to provide a custom presenter. In MVP, your presenter acts as the glue between the model and the view but is also responsible for inflating the view.
This behavior means that providing a custom presenter gives you complete control over the look of a widget. To show you how this works, let’s take the BrowseSupportFragment again.
This fragment expects an object adapter for it to show the individual list rows. The list rows, in turn, want a header item and an item adapter. Then there is the header item presenter, which is used to customize the look of the navigation drawer.
Say, I want the navigation drawer to display icons close to the titles, like this:
In Kotlin, you use this code:
This code provides a custom presenter called IconHeaderItemPresenter by extending the RowHeaderPresenter. The code then overrides three functions:
- onCreateViewHolder the inflator layout. Because this is a presenter, you inflate the layout within the presenter and you’re in complete control of providing any view that you want.
- onBindViewHolder where you set the content.
- onUnbindViewHolder where you free the resources.
This is the minimum set of functions you need to override to customize the presenter.
So, to add the icons you provide a custom view using a linear layout and including a text view, the default, and an image view.
Then, in onBindViewHolder, get an instance of the ViewHolder presenter and the HeaderItem. By getting the HeaderItem, you can call properties such as getName and use those to fill the text view, label, and icon.
Then, you overwrite onUnbindViewHolder to free any resources used.
You can override other functions to customize their look and feel. To do this, back in your activity setHeaderPresentSelector and override with your custom presenter, in this case IconHeaderItemPresenter.
Android TV integration
So far you’ve learned about creating an app that is properly configured for Android TV and has the look and feel you want. The third step in creating a great Android TV app is integrating it with the features and functions of Android TV to help people discover your content and provide them with an engaging experience. I’m going to look at 4 of these integrations:
- Assistant media controls
- The Play Next channel
- Android TV channels
- Assistant media discovery
It’s popular to control media playback on Android TV using voice. Your app can take advantage of this by integrating media sessions to handle the callbacks. Users will be able to perform actions such as:
- play and pause
- skip to the previous channel
- skip to the previous episode
- skip the next item
If you’re using ExoPlayer to play media inside your app, you can get this functionality in just a few lines. Simply create a MediaSession, a MediaSessionConnector and connect it to your player:
You can find the dependencies you need for MediaSessionConnector here:
To instead create this integration from scratch, provide your media session callback by extending MediaSessionCompat.Callback like this:
You can then override all of the functions: onPlay, onPause, onStop, onSeekTo, onSkipToNext, and onSkipToPrevious. You can also override all of the controls and control your own player.
Whether you’re connecting to ExoPlayer or not, remember to set the MediaSession to active in accordance with how your app plays media in the background and don’t combine both approaches. Also be sure to release the MediaSession when playback stops.
By providing these callbacks to your media session instance, your app now responds to the Assistant playback controls. If Android TV is connected to an HDMI-CEC compliant device, it can even handle playback buttons from conventional TV remotes.
Play Next channel
Coming immediately after the user’s favorite apps — the top-most row on the Android TV home screen — the Play Next channel is a global space for peoples’ content from apps. Your app can push content here: content someone didn’t finish watching or other content of interest, such as a movie they haven’t finished or the next episode of a series. As content is added, older content moves to the right and, if the user doesn’t interact with it, is eventually removed.
While you might be eager to get started, let’s set some ground rules of how apps must play nicely inside the Play Next channel. Content inside this space should be limited to traditional movies and TV shows, so avoid adding video clips, game posters or anything else that deviates. Content should also only appear if the user has invested a bit of time into watching, and you should be sure to remove entries when the content has finished (for instance, the end credits begin rolling).
For using this space to recommend content to watch next, make sure that you only do so when adding the next TV episode of a series. In all cases, make sure to use the right “watch next type” and “program type”; doing so helps Android TV reconcile the asset more effectively and provides a high-confidence feature to users. Please read the Watch Next guidelines for app developers carefully before getting started with integrating into the Play Next channel.
To add content to the row, you can publish WatchNextProgram to AndroidX’s PreviewChannelHelper. This uses a builder, so you don’t have to build or worry about the content provider. It’s recommended to add channels on a background thread.
Use setWatchNextType — which could be a movie, a series, or music — to provide a title, description, and URI for poster art. If the content is an item someone has not finished viewing, you can include a progress bar below the content artwork, to show where they stopped viewing, by setting the last engagement time. It’s not recommended to add clips or short videos to Play Next Channel.
Finally, use PreviewChannelHelper to call publishWatchNextProgram.
Android TV Channel
Channels are the rows on the Android TV home screen that enable your app to recommend content. When you create an Android TV app, one channel is added by default but you can have as many channels as you want. However, for other channels, the user has to choose to add them to the home screen.
To add a channel, publish a PreviewChannel and PreviewPrograms to AndroidX’s PreviewChannelHelper. This also uses a builder, so you don’t have to worry about manually creating the content provider. For best performance, it’s recommended to execute this on a background thread.
For the channel, you set the display name, description, and app link intent URI. You can, if you want, set an internal provider ID, a custom ID that you can set to retrieve later.
Next, set a logo.
Finally, build the PreviewChannel.
When you publish your channel by using the helper, you’re returned a channel ID assigned by Android TV.
You can now use this channel ID in a preview builder to build a program.
You’ve seen how to get a flying start with making an Android TV app, from getting the basics right to customizing the Leanback library and integrating with Android TV features to delight your users. Your app can have the look and feel that you want and people will be able to find and control your content directly on TV using Assistant. Now, all that’s left to do is create some great engaging media!