SlideShare a Scribd company logo
Android TV:
Building apps with
Google’s Leanback Library
Joe Birch
Android Engineer @Buffer
@hitherejoe / hitherejoe.com
What is Android TV?
Android TV: Building apps with  Google’s Leanback Library
Build on Material
Build on Material Casual Consumption
Build on Material Casual Consumption
Cinematic Experience
Build on Material Casual Consumption
Cinematic Experience Simplicity
Navigation
Getting around
D-Pad controls
Focus based Navigation
Android TV: Building apps with  Google’s Leanback Library
Setting up
Getting your project ready
<uses-feature
android:name="android.hardware.microphone"
android:required="false"/>
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>
<uses-feature
android:name="android.software.leanback"
android:required="true"/>
<activity
android:name=“com.hitherejoe.vineyard.ui.main.LeanbackActivity”
android:label="@string/app_name"
android:theme="@style/Theme.Leanback">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
github.com/hitherejoe/vineyard
github.com/hitherejoe/bourbon
BrowseFragment
Display browsable content to the user
Android TV: Building apps with  Google’s Leanback Library
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name=“com.hitherejoe.vineyard.ui.fragment.BrowseFragment”
android:id="@+id/main_browse_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Android TV: Building apps with  Google’s Leanback Library
setBrandColor(ContextCompat.getColor(this,
R.color.fastlane_background));
Color color = ContextCompat.getColor(this, R.color.accent);
setSearchAffordanceColor(color);
Drawable badge = ContextCompat.getDrawable(
this, R.drawable.banner_shadow);
setBadgeDrawable(badge);
setHeadersState(HEADERS_ENABLED);
setHeadersState(HEADERS_HIDDEN);
setHeadersState(HEADERS_DISABLED);
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
Browse Fragment
Header Item
Presenter
Header Item
List Row
Array Object
Adapter
Post Adapter
Browse Fragment
Header Item
Presenter
Header Item
List Row
Array Object
Adapter
Post Adapter
public class IconHeaderItemPresenter extends RowHeaderPresenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
// inflate layout
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder,
Object o) {
// set text, icons etc
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
// free resources
}
}
public class IconHeaderItemPresenter extends RowHeaderPresenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
// inflate layout
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder,
Object o) {
// set text, icons etc
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
// free resources
}
}
<android.support.v17.leanback.widget.NonOverlappingLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height=“match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/header_icon"
android:layout_width="32dp"
android:layout_height="32dp"/>
<TextView
android:id="@+id/header_label"
android:layout_marginLeft="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize=“@dimen/header_text”/>
</android.support.v17.leanback.widget.NonOverlappingLinearLayout>
public class IconHeaderItemPresenter extends RowHeaderPresenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
// inflate layout
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder,
Object o) {
// set text, icons etc
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
// free resources
}
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder,
Object o) {
HeaderItem headerItem = ((ListRow) o).getHeaderItem();
setIconDrawable(headerItem.getName(), viewholder.iconImage);
TextView label = viewHolder.headerText;
label.setText(headerItem.getName());
}
public class IconHeaderItemPresenter extends RowHeaderPresenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
// inflate layout
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder,
Object o) {
// set text, icons etc
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
// release bitmaps if used
}
}
setHeaderPresenterSelector(new PresenterSelector() {
@Override
public Presenter getPresenter(Object o) {
return new IconHeaderItemPresenter();
}
});
Browse Fragment
Header Item
Presenter
Header Item
List Row
Array Object
Adapter
Array Object
Adapter
Header Item
List Row
Array Object
Adapter
ArrayObjectAdapter rowAdapter = new ArrayObjectAdapter(this);
rowAdapter.add(…);
HeaderItem header = new HeaderItem(headerPosition, tag);
mRowsAdapter.add(new ListRow(header, rowAdapter));
Browse Fragment
Array Object
Adapter
setOnItemViewClickedListener(mOnItemViewClickedListener);
setOnItemViewSelectedListener(mOnItemViewSelectedListener);
@Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder,
Object item,
RowPresenter.ViewHolder rowViewHolder,
Row row) {
// Do stuff with clicked item object
}
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder,
Object item,
RowPresenter.ViewHolder rowViewHolder,
Row row) {
// Do stuff with selected item object
}
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
BackgroundManager backgroundManager =
BackgroundManager.getInstance(getActivity());
BackgroundManager backgroundManager =
BackgroundManager.getInstance(getActivity());
backgroundManager.attach(getActivity().getWindow());
BackgroundManager backgroundManager =
BackgroundManager.getInstance(getActivity());
backgroundManager.attach(getActivity().getWindow());
backgroundManager.setBitmap(resource);
BackgroundManager backgroundManager =
BackgroundManager.getInstance(getActivity());
backgroundManager.attach(getActivity().getWindow());
backgroundManager.setBitmap(resource);
// Don’t forget to release!!
backgroundManager.release();
SearchFragment
Allow users to search for content
Android TV: Building apps with  Google’s Leanback Library
@Override
public boolean onQueryTextChange(String newQuery)
@Override
public boolean onQueryTextSubmit(String query)
Post Results
(Array Object Adapter)
Search Results
(Array Object Adapter)
Row Adapter
(Array Object Adapter)
Focused item triggers Post search
Android TV: Building apps with  Google’s Leanback Library
VerticalGridFragment
Display a grid of browsable content to the user
Android TV: Building apps with  Google’s Leanback Library
VerticalGridPresenter gridPresenter =
new VerticalGridPresenter();
gridPresenter.setNumberOfColumns(NUM_COLUMNS);
setGridPresenter(gridPresenter);
PlaybackActivity
Display media content on screen
Android TV: Building apps with  Google’s Leanback Library
mSession = new MediaSession(this, getString(R.string.app_name);
mSession.setCallback(new MediaSessionCallback());
mSession.setActive(true);
setMediaController(new MediaController(this,
mSession.getSessionToken());
PlaybackOverlayFragment
Display playback controls to the user
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
mMediaController = getActivity().getMediaController();
mMediaController.registerCallback(mMediaControllerCallback);
private class MediaControllerCallback extends MediaController.Callback {
@Override
public void onPlaybackStateChanged(@NonNull PlaybackState state) { }
@Override
public void onMetadataChanged(@NonNull MediaMetadata metadata) { }
}
ArrayObjectAdapter
(Row Adapter)
ArrayObjectAdapter
(Related Posts)
ArrayObjectAdapter
(Primary Actions)
ArrayObjectAdapter
(Secondary Actions)
PlayBackControlsRow
Meta Data
ControlButtonPresenterSelector presenterSelector =
new ControlButtonPresenterSelector();
mPrimaryActionsAdapter =
new ArrayObjectAdapter(presenterSelector);
mSecondaryActionsAdapter =
new ArrayObjectAdapter(presenterSelector);
mPlaybackControlsRow
.setPrimaryActionsAdapter(mPrimaryActionsAdapter);
mPlaybackControlsRow
.setSecondaryActionsAdapter(mPrimaryActionsAdapter);
public class Action {
private Drawable mIcons;
private CharSequence mLabel1;
private CharSequence mLabel2;
private ArrayList mKeyCodes;
…
}
mPlayPauseAction = new PlayPauseAction(getActivity());
mRepeatAction = new RepeatAction(getActivity());
mSkipNextAction = new SkipNextAction(getActivity());
mSkipPreviousAction = new SkipPreviousAction(getActivity());
mPrimaryActionsAdapter.add(mPlayPauseAction);
mPrimaryActionsAdapter.add(mSkipNextAction);
mPrimaryActionsAdapter.add(mSkipPreviousAction);
mSecondaryActionsAdapter.add(mRepeatAction);
playbackControlsRowPresenter.setOnActionClickedListener(new OnActionClickedListener() {
public void onActionClicked(Action action) {
if (action.getId() == mPlayPauseAction.getId()) {
togglePlayback(mPlayPauseAction.getIndex() == PlayPauseAction.PLAY);
} else if (action.getId() == mSkipNextAction.getId()) {
next(true);
} else if (action.getId() == mSkipPreviousAction.getId()) {
prev(true);
} else if (action.getId() == mRepeatAction.getId()) {
loopVideos();
}
if (action instanceof PlaybackControlsRow.MultiAction) {
notifyChanged(action);
}
}
});
mMediaController.getTransportControls().play();
mMediaController.getTransportControls().pause;
mMediaController.getTransportControls().skipToNext();
mMediaController.getTransportControls().skipToPrevious();
mMediaController.getTransportControls().fastForward;
mMediaController.getTransportControls().rewind();
mMediaController.getTransportControls()
.sendCustomAction(CUSTOM_ACTION_AUTO_LOOP, null);
Post item = (Post) mPlaybackControlsRow.getItem();
item.description = description;
item.username = username;
mPlaybackControlsRow.setTotalTime((int) duration);
mPlaybackControlsRow.setImageDrawable(resource);
mPlaybackControlsRow.setCurrentTime(currentTime);
mPlaybackControlsRow.setBufferedProgress(bufferedT
Post item = (Post) mPlaybackControlsRow.getItem();
item.description = description;
item.username = username;
mPlaybackControlsRow.setTotalTime((int) duration);
mPlaybackControlsRow.setImageDrawable(resource);
mPlaybackControlsRow.setCurrentTime(currentTime);
mPlaybackControlsRow.setBufferedProgress(bufferedTime);
ArrayObjectAdapter
(Adapter Rows)
ArrayObjectAdapter
(Related Posts)
ArrayObjectAdapter
(Primary Actions)
ArrayObjectAdapter
(Secondary Actions)
PlayBackControlsRow
Meta Data
GuidedStepFragment
Display a set of selectable options to the user
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
@Override
public GuidanceStylist.Guidance
onCreateGuidance(Bundle savedInstanceState) {
String title = getString(…);
String description = getString(…);
Drawable icon = getActivity().getDrawable(…);
return new GuidanceStylist.Guidance(
title, description, "", icon);
}
@Override
public void onCreateActions(
@NonNull List<GuidedAction> actions,
Bundle savedInstanceState) {
GuidedAction guidedAction = new GuidedAction.Builder()
.id(…)
.title(…)
.description(…)
.checkSetId(OPTION_CHECK_SET_ID)
.build();
guidedAction.setChecked(isChecked);
actions.add(guidedAction);
}
ErrorFragment
Display an error message to the user
(Because things don’t always go as planned)
Android TV: Building apps with  Google’s Leanback Library
ErrorFragment errorFragment =
new ErrorFragment();
errorFragment.setTitle(…);
errorFragment.setMessage(…);
errorFragment.setButtonText(…);
errorFragment.setButtonClickListener(…);
Custom Views
Because your app doesn’t have to look boring
Tag Card
Tag Card
View
Base Card
View
Text View
Image View
Tag Card
TagCardView cardView = new TagCardView(parent.getContext());
Tag post = (Tag) item;
TagCardView cardView = (TagCardView) viewHolder.view;
if (post.tag != null) {
cardView.setCardText(post.tag);
cardView.setCardIcon(R.drawable.ic_tag);
}
Icon Card
Icon Card
View
Base Card
View
Text View
Image View
Text View
Icon Card
IconCardView cardView = new IconCardView(parent.getContext());
Option option = (Option) item;
IconCardView cardView = (IconCardView) viewHolder.view;
if (option.tag != null) {
cardView.setCardIcon(R.drawable.ic_loop);
cardView.setTitleText(option.title);
cardView.setValueText(option.title);
}
Loading Card
Loading Card
View
Base Card
View
Progress Bar
Loading Card
LoadingCardView cardView = new LoadingCardView(parent.getContext());
IconCardView cardView = (IconCardView) viewHolder.view;
cardView.setIsLoading(true);
Live Card
Live Card
Live Card
View
Base Card
View
Preview Card
View
Looping Video
View
Progress Bar
Image View
View
(Transparent Overlay)
Video View
Live Card
LiveCardView cardView = new LiveCardView(parent.getContext());
Post post = (Post) item;
LiveCardView cardView = (LiveCardView) viewHolder.view;
if (post.videoUrl != null) {
cardView.setTitleText(post.description);
cardView.setContentText(post.username);
cardView.setVideoUrl(post.videoUrl);
Glide.with(cardView.getContext())
.load(post.thumbnailUrl)
.centerCrop()
.error(mDefaultCardImage)
.into(cardView.getMainImageView());
}
Leanback Cards
https://github.com/hitherejoe/LeanbackCards
Android TV: Building apps with  Google’s Leanback Library
Google Guidelines
Android TV: Building apps with  Google’s Leanback Library
Testing.
onView(withId(R.id.title_orb))
.perform(click());
onView(withId(R.id.browse_headers))
.perform(RecyclerViewActions
.actionOnItemAtPosition(i, click()));
onView(withItemText(post.description,
R.id.browse_container_dock))
.perform(click());
Dig deep and remember, everything has IDs!
Android N(utella?)
Picture-in-Picture
Android TV: Building apps with  Google’s Leanback Library
<activity android:name=“.ui.video.VideoActivity”
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges=
“screenSize|smallestScreenSize|screenLayout|orientation" />
@Override
public void onActionClicked(Action action) {
if (action.getId() == R.id.lb_control_picture_in_picture) {
getActivity().enterPictureInPicture();
return;
}
}
@Override
public void onPictureInPictureChanged(boolean inPictureInPicture) {
if (inPictureInPicture) {
// Hide the controls in picture-in-picture mode.
} else {
// Restore the playback UI based on the playback status.
}
}
@Override
public void onPause() {
if (mInPictureInPicture) {
// Continue playback
}
// If paused but not in PIP, pause playback if necessary
}
TV Recording
Sharing Code
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
github.com/hitherejoe/bourbon
What’s next?
The future of TV
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
Android TV: Building apps with  Google’s Leanback Library
Resources
Official Android TV Documentation
github.com/hitherejoe/vineyard
Google Plus Android TV Community
github.com/hitherejoe/AndroidTvBoilerplate
github.com/hitherejoe/leanbackcards
medium.com/@hitherejoe

More Related Content

PDF
Getting your app on Android TV
PDF
React Native on Android TV
ODP
Android TV Overview
PPTX
CLOUD GAMING
PDF
Game Development workshop with Unity3D.
PPT
Introduction to Android, Architecture & Components
PPSX
An Introduction To Game development
PPTX
20 Game Ideas You Should Steal
Getting your app on Android TV
React Native on Android TV
Android TV Overview
CLOUD GAMING
Game Development workshop with Unity3D.
Introduction to Android, Architecture & Components
An Introduction To Game development
20 Game Ideas You Should Steal

What's hot (20)

PPTX
Introduction to game development
PPTX
game development
PPTX
Unity - Essentials of Programming in Unity
PDF
Ionic & Angular
PPTX
Introduction to Game Development
PPTX
LAFS SVI Level 3 - Game Design and Analysis
PPT
Native, Web or Hybrid Mobile App Development?
ODP
Android Camera Architecture
PDF
An introduction to mobile app development and investing
PPTX
Game Design Document - Step by Step Guide
PDF
Android framework design and development
PDF
Introduction to Game Development
PPTX
Introduction to Android and Android Studio
PDF
Cross platform mobile development
PDF
Understanding the Android System Server
PPTX
Android PPT Presentation 2018
PPTX
What is game development
PDF
Mobile games
PPTX
Game development
PPTX
Car racing game for android
Introduction to game development
game development
Unity - Essentials of Programming in Unity
Ionic & Angular
Introduction to Game Development
LAFS SVI Level 3 - Game Design and Analysis
Native, Web or Hybrid Mobile App Development?
Android Camera Architecture
An introduction to mobile app development and investing
Game Design Document - Step by Step Guide
Android framework design and development
Introduction to Game Development
Introduction to Android and Android Studio
Cross platform mobile development
Understanding the Android System Server
Android PPT Presentation 2018
What is game development
Mobile games
Game development
Car racing game for android
Ad

Similar to Android TV: Building apps with Google’s Leanback Library (20)

KEY
Design Patterns for Tablets and Smartphones
PDF
Implementing cast in android
PDF
Android Design Patterns
PPT
Android activity, service, and broadcast recievers
PDF
Slightly Advanced Android Wear ;)
PPTX
What's New in Android
PPTX
Android 3
PDF
Action Bar in Android
PDF
Building Universal Web Apps with React ForwardJS 2017
PDF
Action bar
KEY
Google I/O 2011, Android Honeycomb Highlights
PDF
After max+phonegap
PDF
混搭移动开发:PhoneGap+JQurey+Dreamweaver
PPTX
Android programming basics
PPTX
Embracing the Lollipop
PPTX
Windows Store app using XAML and C#: Enterprise Product Development
PDF
A resource oriented framework using the DI/AOP/REST triangle
PDF
Android accessibility for developers and QA
PDF
Android development for iOS developers
PDF
Android Best Practices
Design Patterns for Tablets and Smartphones
Implementing cast in android
Android Design Patterns
Android activity, service, and broadcast recievers
Slightly Advanced Android Wear ;)
What's New in Android
Android 3
Action Bar in Android
Building Universal Web Apps with React ForwardJS 2017
Action bar
Google I/O 2011, Android Honeycomb Highlights
After max+phonegap
混搭移动开发:PhoneGap+JQurey+Dreamweaver
Android programming basics
Embracing the Lollipop
Windows Store app using XAML and C#: Enterprise Product Development
A resource oriented framework using the DI/AOP/REST triangle
Android accessibility for developers and QA
Android development for iOS developers
Android Best Practices
Ad

Recently uploaded (20)

PPTX
Welding lecture in detail for understanding
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
Sustainable Sites - Green Building Construction
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
CYBER-CRIMES AND SECURITY A guide to understanding
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PPT
Mechanical Engineering MATERIALS Selection
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PDF
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PDF
PPT on Performance Review to get promotions
PPT
CRASH COURSE IN ALTERNATIVE PLUMBING CLASS
PDF
Digital Logic Computer Design lecture notes
PPTX
Construction Project Organization Group 2.pptx
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPTX
Internet of Things (IOT) - A guide to understanding
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
Welding lecture in detail for understanding
Foundation to blockchain - A guide to Blockchain Tech
R24 SURVEYING LAB MANUAL for civil enggi
Sustainable Sites - Green Building Construction
Model Code of Practice - Construction Work - 21102022 .pdf
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
CYBER-CRIMES AND SECURITY A guide to understanding
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
Mechanical Engineering MATERIALS Selection
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PPT on Performance Review to get promotions
CRASH COURSE IN ALTERNATIVE PLUMBING CLASS
Digital Logic Computer Design lecture notes
Construction Project Organization Group 2.pptx
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
Internet of Things (IOT) - A guide to understanding
UNIT-1 - COAL BASED THERMAL POWER PLANTS

Android TV: Building apps with Google’s Leanback Library