Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Developing an Android TV app

Developing an Android TV app

There have been several attempts at conquering the users’ living room by offering the perfect entertainment device. Android TV is Google’s latest effort to this end, which offers a sofa-tuned user interface based on Android Lollipop. Will you, as a developer, miss out the chance of bringing your content to the party?

This presentation will walk you through the building blocks of the TV-centric libraries and widgets offered by the Android framework. There will be code snippets, best practices and more advanced techniques.

Sebastiano Gottardo

April 15, 2015

More Decks by Sebastiano Gottardo

Other Decks in Programming


  1. The Android TV platform 3 What is it? It’s Android.

    For TVs. So cool. What is it for? It’s an entertainment platform, with multimedia content in mind. How can I get one? Get a Nexus Player, or get a TV/device from one of the OEM partners.
  2. Key concepts • “Simple. Cinematic. Beautiful.”
 The interface has to

    be easy to understand and navigate. In its simplicity, it should also be catchy and amaze the user. • Multimedia is what this is all about
 TVs are meant to consume multimedia content, such as images, audio, video and gaming. Leave all the rest out. • Ease access to the content you’re offering
 Avoid complex functions and interactions to provide a fast and streamlined experience. 4
  3. Leanback support library: explained! • What is it?
 It is

    a support library build by Google for you to build awesome TV experiences with your app. • What is it for?
 It offers a set of UI widgets that are specifically tailored for TV devices and that ease the developer’s task of displaying content on TVs. • How can I get it?
 Gradle. 6 dependencies { compile 'com.android.support:leanback-v17:21.0.0' }
  4. Leanback: building blocks ‣ BrowseFragment ‣ DetailsFragment ‣ SearchFragment ‣

    VerticalGridFragment ‣ ErrorFragment ‣ PlaybackOverlayFragment 7
  5. 8 • The main architectural design pattern across the Leanback

    library is called Model-View-Presenter • If you’re familiar with MVC, the main difference is that the View does never bind to the Model, but only depends on the Presenter instead • This is good for achieving separation between the layers and for testing (allows using mock views) ProTip: MVP
  6. BrowseFragment • The main component of a TV application, used

    “to create a primary layout for browsing categories and rows of media items [with a minimum of code” • It is composed of a list of categories on the left (“headers”, by means of a HeadersFragment) and a list of rows on the right (“rows”, by means of a RowsFragment) • Rows on the right have a corresponding header on the left 10
  7. BrowseFragment: load elements 11 private void loadRows(ArrayList<MXMCoreTrack> tracks) { mRowsAdapter

    = new ArrayObjectAdapter(new ListRowPresenter()); ! // adding the 'Popular' element ArrayObjectAdapter popularRowAdapter = new ArrayObjectAdapter(new CardPresenter()); popularRowAdapter.addAll(0, tracks); ! HeaderItem popularHeader = new HeaderItem(0, "Popular", null); ListRow popularRow = new ListRow(popularHeader, popularRowAdapter); mRowsAdapter.add(popularRow); ! // adding the 'Top Genres' elements // adding the 'Other genres' elements ! setAdapter(mRowsAdapter); }
  8. DetailsFragment in detail • Use it to display information about

    the content just selected by the user • Automatically matches the brand color • You can provide an additional row of related items 18
  9. DetailsFragment example 23 private void loadDetails(MXMCoreTrack track) { DetailsOverviewRow row

    = new DetailsOverviewRow(track); row.setImageBitmap(getActivity(), getImage(track)); row.addAction(new Action(0, "Play")); row.addAction(new Action(1, "Add to queue")); DetailsOverviewRowPresenter presenter = new DetailsOverviewRowPresenter(new DetailsPresenter()); ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenter); adapter.add(row); setAdapter(adapter); } ! private static class DetailsPresenter extends AbstractDetailsDescriptionPresenter { ! @Override protected void onBindDescription(ViewHolder viewHolder, Object o) { MXMCoreTrack track = (MXMCoreTrack) o; viewHolder.getTitle().setText(track.getTrackName()); viewHolder.getSubtitle().setText(track.getArtistName()); viewHolder.getBody().setText("Honestly. I can't take no more of this song."); } }
  10. SearchFragment • Accessed by the top left “Search orb” •

    User can search stuff with it • Results can be shown in single/multiple rows 25
  11. SearchFragment 1/2 26 public class TVSearchFragment extends SearchFragment implements SearchFragment.SearchResultProvider

    { ! private ArrayObjectAdapter mRowsAdapter; private ArrayObjectAdapter mListRowAdapter; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ! mListRowAdapter = new ArrayObjectAdapter(new CardPresenter()); mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); setSearchResultProvider(this); } ! @Override public ObjectAdapter getResultsAdapter() { return mRowsAdapter; } ! ... ! }
  12. SearchFragment 2/2 29 ... ! @Override public boolean onQueryTextChange(String newQuery)

    { // the query text has changed return true; } ! @Override public boolean onQueryTextSubmit(String query) { // the query has been submitted return true; } ! public void updateSearchResult(ArrayList<MXMCoreTrack> tracks) { mListRowAdapter.clear(); mListRowAdapter.addAll(0, tracks); mRowsAdapter.add(new ListRow(mListRowAdapter)); } }
  13. VerticalGridFragment 30 ✓ Can be used to display a long

    list of elements in a vertical fashion.
  14. Leanback: pros & cons • Offers a set of widget

    optimized out-of-the-box to for TVs • D-PAD navigation just works! And so does the mic. • Can be customized (to a certain degree) • Since most apps rely on it, a user easily acquaints to the way it works • Hard to go wrong
 • Forces a predefined design pattern 33
  15. The biggest limitation • BrowseFragment displays a list of rows

    (right side) together with a list of headers (left side), but… • You cannot map more than one row to the same header
 • Things like sub-categories or custom fragments simply don’t play along with BrowseFragment • This limitation is way too big to be ignored in some circumstances 34
  16. CustomBrowseFragment? • Hard • You can recreate its structure by

    using a HeadersFragment and a RowsFragment • That’s what I did! 35 https://medium.com/building-for-android-tv https://github.com/dextorer/BuildingForAndroidTV
  17. Porting your app? • Bootstrap
 Brand new code is good

    for your health, and it feels refreshing. Plus, you get the chance of experimenting new libraries and new design patterns. Takes longer though, so pay attention to that. • Play Store entry
 Benefit from the same reviews, download counts, visibility, featuring.. Or not, depends on your current status! • APK size
 Adding more TV resources may give your users #YARTC (Yet Another Reason To Complain). 37 At Musixmatch, we decided for a fresh start.
  18. BackgroundManager • The BackgroundManager class allows you to load a

    background image on the current Activity’s Window • Extremely handy, adds a very nice effect 38 private void prepareBackgroundManager() { BackgroundManager backgroundManager = BackgroundManager.getInstance(getActivity()); backgroundManager.attach(getActivity().getWindow()); // backgroundManager.setBitmap(bitmap); mBackgroundTarget = new PicassoBackgroundManagerTarget(backgroundManager); } ! protected void updateBackground(URI uri) { Picasso.with(getActivity()) .load(uri.toString()) .transform(new BlurTransformation(getActivity())) .into(mBackgroundTarget); }
  19. Remaining visible on home Some applications are able to keep

    playing the current video even when the user presses the Home button. How? 40 boolean visible = requestVisibleBehind(true); • Call it between onResume and onPause • Success is determined by the boolean result • Only available to fullscreen opaque activities (no dialogs, folks)
  20. Recommending your content • Easy way to promote your content

    • New items automatically appears on the home screen • Notifications at the core! (uses NotificationBuilder on a Service) 41
  21. Make your app global-searchable • On Android TV, users can

    use the mic from anywhere to begin a search • Google Now-style • Your results can be there as well! • Can be done by creating a custom content provider 42 https://developer.android.com/training/tv/discovery/searchable.html
  22. Useful resources • Official documentation: http://developer.android.com/tv/index.html • Building for Android

    TV: https://medium.com/building-for-android-tv/ 43 Who to follow @rotxed +SebastianoGottardo @ph0b +XavierHallade @dggonzales +DavidGonzales