Android TV Dev Guide for L-Preview
Change-Id: I46749538c927e1090c73e747e44e83aa703bdff1
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index 377c487..162c3a9 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -24,6 +24,42 @@
<li><a href="<?cs var:toroot ?>preview/material/animations.html">Animations</a></li>
</ul>
</li>
+
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>preview/tv/index.html">TV</a>
+ </div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>preview/tv/start/index.html">
+ Get Started</a></li>
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>preview/tv/ui/index.html">
+ User Interface</a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/layouts.html">
+ Layouts</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/navigation.html">
+ Navigation</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/browse.html">
+ BrowseFragment</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/details.html">
+ DetailsFragment</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/in-app-search.html">
+ In-App Search</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/ui/recommendations.html">
+ Recommendations</a></li>
+ </ul>
+ </li>
+ <li><a href="<?cs var:toroot ?>preview/tv/games/index.html">
+ Games on TV</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/start/hardware-features.html">
+ Hardware Features</a></li>
+ <li><a href="<?cs var:toroot ?>preview/tv/adt-1/index.html">
+ ADT-1</a></li>
+ </ul>
+ </li>
+
<li class="nav-section">
<div class="nav-section-header empty">
<a href="<?cs var:toroot ?>preview/samples.html">Samples</a>
diff --git a/docs/html/preview/tv/adt-1/index.jd b/docs/html/preview/tv/adt-1/index.jd
new file mode 100644
index 0000000..47bab23
--- /dev/null
+++ b/docs/html/preview/tv/adt-1/index.jd
@@ -0,0 +1,19 @@
+page.title=ADT-1 Developer Kit
+page.tags="emote","e-mote","adt"
+
+@jd:body
+
+<p>Information about the ADT-1 developer kit, including:</p>
+
+<ul>
+ <li>General description and FAQ</li>
+ <li>Emote info and deep link to Play Store</li>
+ <li>Regulatory Notifications (FCC and Industry Canada)</li>
+</ul>
+
+
+<p>To be included, but not listed on page:</p>
+
+<ul>
+ <li><a href="request.html">ADT-1 Request Page</a></li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/preview/tv/adt-1/request.jd b/docs/html/preview/tv/adt-1/request.jd
new file mode 100644
index 0000000..dc13de0
--- /dev/null
+++ b/docs/html/preview/tv/adt-1/request.jd
@@ -0,0 +1,5 @@
+page.title=Request ADT-1 Developer Kit
+
+@jd:body
+
+<p>Request form for the ADT-1 developer kit</p>
\ No newline at end of file
diff --git a/docs/html/preview/tv/games/index.jd b/docs/html/preview/tv/games/index.jd
new file mode 100644
index 0000000..9471df0
--- /dev/null
+++ b/docs/html/preview/tv/games/index.jd
@@ -0,0 +1,66 @@
+page.title=Games on TV
+page.tags="controller"
+
+@jd:body
+
+<p>This document complements the larger best-practice guidelines for [Design for TV](TODO, use formal name of referenced doc, and add link). It assumes that you have read those guidelines, and seeks to minimize repetition.</p>
+<h3>Overview</h3>
+<p>Because of factors including its large size, its control scheme, and its nature as a shared display, the television screen presents a number of considerations that may be new to mobile developers. This document breaks these considerations down into five sections:</p>
+<ul>
+<li>Display</li>
+<li>Control</li>
+<li>Manifest</li>
+<li>Google Play Game Services</li>
+<li>Web</li>
+</ul>
+<h3>Display</h3>
+<h4>A shared display</h4>
+<p>A living-room TV presents design challenges for multiplayer games, in that all of the players can see everything. This issue is especially germane to games (such as card games or strategy games) that rely on each player’s possession of hidden information.</p>
+<p>Some mechanisms you can implement to address the problem of one player’s “eavesdropping” on another’s information are:</p>
+<ul>
+<li>In a turn-based game, like a word or card game, one player at a time might view the display. On finishing her move, the game allows the player to cover the screen with a “blinder”. When the next player takes his turn, he opens the blinder to reveal the information he’s allowed to be seeing.</li>
+<li>Using a second screen, such as a phone or tablet, can enable a player to conceal information. For information on implementing second-screen support, see <a href="http://developer.android.com/reference/android/app/Presentation.html">Presentation</a> on the Android developer site.</li>
+</ul>
+<h4>No touch interface</h4>
+<p>A television does not have a touch interface. Your game design, therefore, need not take into account the possibility that a player’s controlling fingers might block the on-screen action. You can assume constant visibility of the entire viewing area.</p>
+<p>See the Control section in this document and in [Design for TV](TODO, use formal name of referenced doc, and add link) for more implications of the lack of touch interface.</p>
+<h4>Landscape display</h4>
+<p>In mobile-device terms, a TV is always “sideways.” You can’t turn it, and there is no portrait orientation. You should always be designing your TV games to be displayed in landscape mode.</p>
+<h3>Control</h3>
+<h4>D-pad</h4>
+<p>Because of the lack of touch interface, you should be planning your control scheme based on a D-pad. Some key points to keep in mind include:</p>
+<p>The player needs to use the gamepad in all aspects of the game–not just controlling core gameplay, but also navigating menus and ads. For this reason, you should also ensure that your Android TV game does not refer to a touch interface: for example, an Android TV game cannot tell a player to "Tap to skip".</p>
+<p>You can avoid unhappy surprises (and resulting low ratings) by using your Play Store description to communicate to the player any expectations about controllers. If a game is better suited to a gamepad with a joystick than one with only a D-pad, you should make this clear. A player who uses an ill-suited controller for a game is likely to have a subpar experience–and penalize your game in the ratings.</p>
+<p>You can also help ensure a good player experience by ensuring that button mapping is intuitive and flexible. A widely accepted standard has the A button serving to <code>Accept</code>, and the B button serving to <code>Cancel</code>. You can also offer flexibility in the form of remappability. For more information on button mapping, <a href="http://developer.android.com/training/game-controllers/controller-input.html">Handling Controller Actions</a>.</p>
+<p>Your game can also contribute to a good match between controller and game by querying the controller about its capabilities. For example, you may intend for a player to steer an object by waving the controller in the air. If a player's controller lacks accelerometer and gyroscope hardware, however, waving will not work. But when your game queries the controller and discovers that motion detection is not supported, it can switch over to an alternative, available control scheme.</p>
+<p>For more information on querying controller capabilities, see <a href="http://developer.android.com/training/game-controllers/compatibility.html">Supporting Controllers Across Android Versions</a>.</p>
+<h4>Back-button behavior</h4>
+<p>The Back button should never act as a toggle. For example, do not use it to both open and close a menu. Its behavior should only be linear. For example: Game play > Game pause screen > Game main screen > Android home screen.</p>
+<p>With this principle of "linear navigation" in mind, the back button may leave an in-game menu (opened by a different button) to return to gameplay.</p>
+<h4>Handling multiple controllers</h4>
+<p>When multiple players are playing a game, each with his or her own controller, it is important to map each player-controller pair. For information on how to implement controller-number identification, see <a href="http://developer.android.com/reference/android/view/InputDevice.html#getControllerNumber(">Input Devices</a>) on the Android developer site.</p>
+<h4>Handling disconnects</h4>
+<p>When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog should appear prompting the disconnected player to reconnect his or her controller.</p>
+<p>The dialog should also offer troubleshooting tips (e.g., "Check your Bluetooth connection").</p>
+<h3>Manifest</h3>
+<p>Games are displayed in a separate row from regular apps in the launcher. Android TV uses the <code>android:isGame</code> flag to differentiate games from non-game apps. You can assign it a value of either <code>true</code> or <code>false</code>. </p>
+<pre class="fragment"><application>
+ . . .
+ <meta-data android:name="isGame" android:value=["true" | "false"]/>
+android:isGame=["true" | "false"] >
+ . . .
+</application>
+</pre><h3>Google Play Game Services</h3>
+<p>If your game integrates Google Play Game Services, you should keep in mind a number of considerations pertaining to achievements, sign-on, saving games, and multiplayer play.</p>
+<h4>Achievements</h4>
+<p>Your game should include at least five (earnable) achievements. Only a user controlling gameplay from a supported input device should be able to earn achievements.</p>
+<h4>Sign-on</h4>
+<p>Your game should attempt to sign the user in on launch. If the player declines sign-in several times in a row, your game should stop asking.</p>
+<h4>Saving</h4>
+<p>We highly recommend using Play Services cloud save to store your game save. Your game should bind game saves to a specific Google account, so as to be uniquely identifiable, even across devices: Whether the player is using her phone or her tablet, the game should be able to pull the same game-save information from her account.</p>
+<p>You should also provide an option in your game's UI to prompt the player to destroy save data. You might put the option in the game's <code>Settings</code> screen.</p>
+<h4>Multiplayer experience</h4>
+<p>A game offering a multiplayer experience must allow at least two players to enter a room.</p>
+<h3>Web</h3>
+<p>Android TV games do not support a full web browser. You should therefore avoid using generic URLs in your game.</p>
+<p>Webviews will work for logins to services like Google+ and Facebook. </p>
diff --git a/docs/html/preview/tv/images/atv.png b/docs/html/preview/tv/images/atv.png
new file mode 100644
index 0000000..cd96164
--- /dev/null
+++ b/docs/html/preview/tv/images/atv.png
Binary files differ
diff --git a/docs/html/preview/tv/images/browsefragment.png b/docs/html/preview/tv/images/browsefragment.png
new file mode 100644
index 0000000..8998b13
--- /dev/null
+++ b/docs/html/preview/tv/images/browsefragment.png
Binary files differ
diff --git a/docs/html/preview/tv/images/detailsfragment.png b/docs/html/preview/tv/images/detailsfragment.png
new file mode 100644
index 0000000..014ab23
--- /dev/null
+++ b/docs/html/preview/tv/images/detailsfragment.png
Binary files differ
diff --git a/docs/html/preview/tv/images/home-recommendations.png b/docs/html/preview/tv/images/home-recommendations.png
new file mode 100644
index 0000000..2c18827
--- /dev/null
+++ b/docs/html/preview/tv/images/home-recommendations.png
Binary files differ
diff --git a/docs/html/preview/tv/index.jd b/docs/html/preview/tv/index.jd
new file mode 100644
index 0000000..da40985
--- /dev/null
+++ b/docs/html/preview/tv/index.jd
@@ -0,0 +1,12 @@
+page.title=Android on TV
+
+@jd:body
+
+<img src="{@docRoot}preview/tv/images/atv.png" align="middle"/>
+
+<p>Android offers a rich user experience that's optimized for apps running on large screen
+ devices, such as high-definition televisions. Apps on TV offer new opportunities to
+ delight your users from the comfort of their couch.</p>
+
+<a href="{@docRoot}preview/tv/start/index.html">Get Started ></a>
+
diff --git a/docs/html/training/tv/unsupported-features-tv.jd b/docs/html/preview/tv/start/hardware-features.jd
similarity index 74%
rename from docs/html/training/tv/unsupported-features-tv.jd
rename to docs/html/preview/tv/start/hardware-features.jd
index a9f090b..3c1cd78 100644
--- a/docs/html/training/tv/unsupported-features-tv.jd
+++ b/docs/html/preview/tv/start/hardware-features.jd
@@ -1,22 +1,15 @@
-page.title=Handling Features Not Supported on TV
-parent.title=Designing for TV
-parent.link=index.html
-
-trainingnavtop=true
-previous.title=Optimizing Navigation for TV
-previous.link=optimizing-navigation-tv.html
+page.title=Hardware Features on TV
+page.tags="unsupported"
@jd:body
-<div id="tb-wrapper">
-<div id="tb">
-
-<h2>This lesson teaches you to</h2>
-<ol>
- <li><a href="#WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</a></li>
- <li><a href="#CheckAvailableFeatures">Check for Available Features at Runtime</a></li>
-</ol>
-
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#WorkaroundUnsupportedFeatures">Handle Unsupported Features</a></li>
+ <li><a href="#CheckAvailableFeatures">Check Available Features</a></li>
+ </ol>
</div>
</div>
@@ -30,8 +23,8 @@
</ul>
<p>
-Because TVs have a different purpose from other devices, they usually don't have hardware features
-that other Android-powered devices often have. For this reason, the Android system does not
+Because TVs have a different purpose from other devices, they usually don't have hardware features
+that other Android-powered devices often have. For this reason, the Android system does not
support the following features for a TV device:
<table>
<tr>
@@ -69,39 +62,39 @@
This lesson shows you how to work around features that are not available on TV by:
<ul>
<li>Providing work arounds for some non-supported features.</li>
- <li>Checking for available features at runtime and conditionally activating/deactivating certain code
+ <li>Checking for available features at runtime and conditionally activating/deactivating certain code
paths based on availability of those features.</li>
</ul>
</p>
-<h2 id="WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</h2>
+<h2 id="WorkaroundUnsupportedFeatures">Handle Unsupported Features</h2>
<p>
-Android doesn't support touchscreen interaction for TV devices, most TVs don't have touch screens,
-and interacting with a TV using a touchscreen is not consistent with the 10 foot environment. For
-these reasons, users interact with Android-powered TVs using a remote. In consideration of this,
-ensure that every control in your app can be accessed with the D-pad. Refer back to the previous two lessons
-<a href="{@docRoot}training/tv/optimizing-layouts-tv.html">Optimizing Layouts for TV</a> and
+Android doesn't support touchscreen interaction for TV devices, most TVs don't have touch screens,
+and interacting with a TV using a touchscreen is not consistent with the 10 foot environment. For
+these reasons, users interact with Android-powered TVs using a remote. In consideration of this,
+ensure that every control in your app can be accessed with the D-pad. Refer back to the previous two lessons
+<a href="{@docRoot}training/tv/optimizing-layouts-tv.html">Optimizing Layouts for TV</a> and
<a href="{@docRoot}training/tv/optimizing-navigation-tv.html">Optimize Navigation for TV</a> for
-more details
-on this topic. The Android system assumes that a device has a touchscreen, so if you want your application
+more details
+on this topic. The Android system assumes that a device has a touchscreen, so if you want your application
to run on a TV, you must <strong>explicitly</strong> disable the touchscreen requirement in your manifest file:
<pre>
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
</pre>
-</p>
+</p>
<p>
-Although a TV doesn't have a camera, you can still provide a photography-related application on a TV.
-For example, if you have an app that takes, views and edits photos, you can disable its picture-taking
-functionality for TVs and still allow users to view and even edit photos. The next section talks about how to
+Although a TV doesn't have a camera, you can still provide a photography-related application on a TV.
+For example, if you have an app that takes, views and edits photos, you can disable its picture-taking
+functionality for TVs and still allow users to view and even edit photos. The next section talks about how to
deactivate or activate specific functions in the application based on runtime device type detection.
</p>
<p>
-Because TVs are stationary, indoor devices, they don't have built-in GPS. If your application uses location
-information, allow users to search for a location or use a "static" location provider to get
+Because TVs are stationary, indoor devices, they don't have built-in GPS. If your application uses location
+information, allow users to search for a location or use a "static" location provider to get
a location from the zip code configured during the TV setup.
<pre>
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
@@ -120,18 +113,18 @@
</p>
<p>
-TVs usually don't support microphones, but if you have an application that uses voice control,
+TVs usually don't support microphones, but if you have an application that uses voice control,
you can create a mobile device app that takes voice input and then acts as a remote control for a TV.
</p>
-<h2 id="CheckAvailableFeatures">Check for Available Features at Runtime</h2>
+<h2 id="CheckAvailableFeatures">Check Available Features</h2>
<p>
-To check if a feature is available at runtime, call
+To check if a feature is available at runtime, call
{@link android.content.pm.PackageManager#hasSystemFeature(String)}.
- This method takes a single argument : a string corresponding to the
-feature you want to check. For example, to check for touchscreen, use
-{@link android.content.pm.PackageManager#hasSystemFeature(String)} with the argument
+ This method takes a single argument : a string corresponding to the
+feature you want to check. For example, to check for touchscreen, use
+{@link android.content.pm.PackageManager#hasSystemFeature(String)} with the argument
{@link android.content.pm.PackageManager#FEATURE_TOUCHSCREEN}.
</p>
@@ -152,6 +145,6 @@
</p>
<p>
-This is just one example of using runtime checks to deactivate app functionality that depends on features
+This is just one example of using runtime checks to deactivate app functionality that depends on features
that aren't available on TVs.
</p>
\ No newline at end of file
diff --git a/docs/html/preview/tv/start/index.jd b/docs/html/preview/tv/start/index.jd
new file mode 100644
index 0000000..7f726bd
--- /dev/null
+++ b/docs/html/preview/tv/start/index.jd
@@ -0,0 +1,193 @@
+page.title=Get Started with TV Apps
+page.tags="leanback","recyclerview","launcher"
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#prerequisites">Prerequisites</a></li>
+ <li><a href="#dev-project">Setup a TV Project</a>
+ <ul>
+ <li><a href="#tv-activity">Create a TV Activity</a></li>
+ <li><a href="#tv-libraries">Add TV Support Libraries</a></li>
+ </ul>
+ </li>
+ <li><a href="#build-it">Build TV Apps</a></li>
+ </ol>
+</div>
+</div>
+
+<p>This guide describes how to prepare your development environment and projects for building
+ TV apps, including updating your existing app to run on TV devices.</p>
+
+
+<h2 id="prerequisites">Prerequisites</h2>
+
+<p>Before you begin setting up to build apps for TV, you must:</p>
+
+<ul>
+ <li><strong><a href="{@docRoot}preview/setup-sdk.html">
+ Setup the Preview SDK</a></strong>
+ <br>
+ The preview SDK provides the developer tools needed to build and test apps for TV.
+ </li>
+ <li><strong><a href="{@docRoot}preview/setup-sdk.html#project">
+ Create a Preview SDK Project</a></strong>
+ <br>
+ In order to access new APIs for TV devices, you must create a project that targets the preview
+ release level or modify an existing project to target the preview release.
+ </li>
+</ul>
+
+
+<h2 id="dev-project">Setup a TV Project</h2>
+
+<p>TV apps use the same structure as those for phones and tablets. This means you can modify
+ your existing apps to also run on TV devices or create new apps based on what you already know
+ about building apps for Android. This section discusses how to modify an existing app or create a
+ new app that runs on TV devices.</p>
+
+<p>There are the main steps to creating an app that runs on TV devices, only the first of these
+ is required:</p>
+
+<ul>
+ <li><strong>Activity for TV</strong> - (Required) Your application must have an activity that is
+ is declared to run on TV devices through an app manifest entry.</li>
+ <li><strong>TV Support Libraries</strong> - (Optional) There are several Support Libraries
+ available for TV devices that provide user interface widgets for building user interfaces
+ for use on TV.</li>
+</ul>
+
+
+<h3 id="tv-activity">Create a TV Activity</h3>
+
+<p>Applications that are intended to run on TV devices must declare a launcher activity for TV
+ in their manifest using a the {@code android.intent.category.LEANBACK_LAUNCHER} intent filter.
+ This filter identifies your app as being built for TV, enabling your app to be displayed in the
+ Google Play app running on TV devices. Declaring this intent also identifies which activity in
+ your app should be launched when a user selects your app icon on a TV.</p>
+
+<p class="caution">
+ <strong>Caution:</strong> If you do not include the LEANBACK_LAUNCHER intent filter in your app,
+ it will not be visible to users running the Google Play store on TV devices. If your load an app
+ without this intent filter onto a TV device using developer tools, the app does not appear in
+ the TV user interface.
+</p>
+
+<p>The following code snippet shows how to include this intent filter in your manifest:</p>
+
+<pre>
+<application>
+ ...
+ <activity
+ android:name="com.example.android.MainActivity"
+ android:label="@string/app_name" >
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="com.example.android.<strong>TvActivity</strong>"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.NoTitleBar">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="<strong>android.intent.category.LEANBACK_LAUNCHER</strong>" />
+ </intent-filter>
+
+ </activity>
+</application>
+</pre>
+
+<p>The second activity manifest entry in the example above specifies that it should be used as
+ the main activity when your app launched on an TV device.</p>
+
+<p>If you have an existing app that you are modifying for TV use, your app should not use the same
+ activity layout for TV that you do for phones and tablets. The user interface of your TV app (or
+ TV portion of your existing app) should provide a simpler interface that can be easily navigated
+ using a remote control from a couch. For guidelines on designing an app for TV, see the
+ <a href="{@docRoot}design/tv/index.html">TV Design</a> guide. For more instructions on
+ developing a user interface that is appropriate to TV, see the
+ <a href="{@docRoot}preview/tv/ui/index.html">TV User Interface</a> guide.
+</p>
+
+
+<h3 id="tv-libraries">Add TV Support Libraries</h3>
+
+<p>The Preview SDK includes support libraries that are intended for use with TV apps. These
+ libraries provide APIs and user interface widgets for use on TV devices. The libraries are
+ located in the {@code <sdk>/extras/android/support/} directory where you installed the
+ Preview SDK. Here is a list of the libraries and their general purpose:</p>
+
+<ul>
+ <li><strong>v17 leanback library</strong> - Provides user interface widgets for TV, including
+ {@code BrowseFragment}, {@code DetailsFragment}, and {@code SearchFragment}.
+ <ul>
+ <li>SDK location: {@code <sdk>/extras/android/support/v17/leanback}</li>
+ <li>Gradle dependency: {@code com.android.support:leanback-v17:20.0.+}</li>
+ <li>Contains resources: Yes</li>
+ </ul>
+ </li>
+ <li><strong>v7 recyclerview library</strong> - Provides classes for managing display of long
+ lists in a memory efficient manner. Several classes in the v17 leanback library depend on the
+ classes in this library.
+ <ul>
+ <li>SDK location: {@code <sdk>/extras/android/support/v7/recyclerview}</li>
+ <li>Gradle dependency: {@code com.android.support:recyclerview-v7:20.0.+}</li>
+ <li>Contains resources: No</li>
+ </ul>
+ </li>
+</ul>
+
+<p class="note">
+ <strong>Note:</strong> You are not required to use these support libraries for your TV app.
+ However, we strongly recommend using them, particularly for apps that provide a media catalog
+ browsing interface.
+</p>
+
+<p>If you decide to use the v17 leanback library for your application, you should note that it is
+ dependent on the <a href="{@docRoot}tools/support-library/features.html#v7-appcompat">v7
+ appcompat library</a>, which is, in turn, dependent on the
+ <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. This means
+ that apps that use the leanback support library should include all of these support
+ libraries:</p>
+
+<ul>
+ <li>v17 leanback support library</li>
+ <li>v7 recyclerview support library</li>
+ <li>v7 appcompat support library</li>
+ <li>v4 support library</li>
+</ul>
+
+<p>Two of these libraries (v17 leanback and v7 appcompat) contain resources, which require
+ you to take specific steps to include them in app projects. For instructions on
+ importing a support library with resources, see
+ <a href="http://developer.android.com/tools/support-library/setup.html#libs-with-res">
+ Support Library Setup</a>.
+</p>
+
+
+<h2 id="build-it">Build TV Apps</h2>
+
+<p>After you have completed the steps described above, it's time to start building apps for
+ the big screen! Check out these additional topics to help you build your app for TV:
+
+<ul>
+ <li><a href="{@docRoot}preview/tv/ui/index.html">User Interface</a> - The user interface of
+ TV devices is different from those of other Android devices. See this topic to find out how
+ to build TV user interfaces and the widgets provided to make it easier to build them.
+ </li>
+ <li><a href="{@docRoot}preview/tv/games/index.html">Games for TV</a> - TV devices are great
+ platforms for games. See this topic for information on building great game experiences for
+ TV.</li>
+ <li><a href="{@docRoot}preview/tv/start/hardware-features.html">Hardware features</a> - TV
+ devices do not contain hardware features normally found on other Android devices. See this
+ topic for information on unsupported hardware features and what to do about them.
+ </li>
+</ul>
diff --git a/docs/html/preview/tv/ui/browse.jd b/docs/html/preview/tv/ui/browse.jd
new file mode 100644
index 0000000..b74c209
--- /dev/null
+++ b/docs/html/preview/tv/ui/browse.jd
@@ -0,0 +1,216 @@
+page.title=BrowseFragment
+parent.title=User Interfaces for TV
+parent.link=index.html
+
+trainingnavtop=true
+next.title=DetailsFragment
+next.link=details.html
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#layout">Media Browse Layout</a></li>
+ <li><a href="#lists">Displaying Media Lists</a></li>
+ <li><a href="#background">Updating the Background</a></li>
+ </ol>
+
+</div>
+</div>
+
+<p>The Leanback support library provides several APIs for displaying and browsing media catalogs
+ on the TV devices. This lesson discusses how to use the classes provided by this library to
+ implement a user interface for browsing music or videos from your app's media catalog.</p>
+
+
+<h2 id="layout">Media Browse Layout</h2>
+
+<p>The BrowseFragment class in the Leanback support library allows you to create a primary
+ layout for browsing categories and rows of media items with a minimum of code. The following
+ example layout shows how to create a layout that contains a BrowseFragment:</p>
+
+<pre>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+
+ <fragment
+ <strong>android:name="android.support.v17.leanback.app.BrowseFragment"</strong>
+ android:id="@+id/browse_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+</LinearLayout>
+</pre>
+
+<p>In order to work with this layout in an activity, retrieve the BrowseFragment element from
+ the layout. Use the BrowseFragment.Params class to set display parameters such as the icon, title
+ and whether category headers are enabled. The following code sample demonstrates how to set the
+ layout parameters for a BrowseFragment in a layout:</p>
+
+<pre>
+public class BrowseMediaActivity extends Activity {
+
+ public static final String TAG ="BrowseActivity";
+
+ protected BrowseFragment mBrowseFragment;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.browse_fragment);
+
+ final FragmentManager fragmentManager = getFragmentManager();
+ <strong>mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById(
+ R.id.browse_fragment);</strong>
+
+ // Set display parameters for the BrowseFragment
+ BrowseFragment.Params params = mBrowseFragment.getBrowseParams();
+ if (params == null) {
+ params = new BrowseFragment.Params();
+ }
+ params.setHeadersState(BrowseFragment.HEADERS_ENABLED);
+ params.setTitle(getString(R.string.app_name));
+ params.setBadgeImage(getResources().getDrawable(R.drawable.ic_launcher));
+ mBrowseFragment.setBrowseParams(params);
+
+ }
+}
+</pre>
+
+
+<h2 id="lists">Displaying Media Lists</h2>
+
+<p>The BrowseFragment allows you to define and display browseable media content categories and
+ media items from a media catalog using adapters and presenters. Adapters enable you to connect to
+ local or online data sources that contain your media catalog information. Presenter classes hold
+ data about media items and provide layout information for displaying an item on screen.</p>
+
+<p>The following example code shows an implementation of a presenter for displaying string
+ data:</p>
+
+<pre>
+public class StringPresenter extends Presenter {
+ private static final String TAG = "StringPresenter";
+
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ TextView textView = new TextView(parent.getContext());
+ textView.setFocusable(true);
+ textView.setFocusableInTouchMode(true);
+ textView.setBackground(
+ parent.getContext().getResources().getDrawable(R.drawable.text_bg));
+ return new ViewHolder(textView);
+ }
+
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ ((TextView) viewHolder.view).setText(item.toString());
+ }
+
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ Log.d(TAG, "onUnbindViewHolder");
+ }
+}
+</pre>
+
+<p>Once you have constructed a presenter class for your media items, you can build and attach an
+ adapter to the BrowseFragment to display those items on screen for browsing by the user. The
+ following example code demonstrates how to construct an adapter to display categories and items
+ in those categories using the StringPresenter class shown in the previous code example:</p>
+
+<pre>
+private ArrayObjectAdapter mRowsAdapter;
+private static final int NUM_ROWS = 4;
+
+@Override
+protected void onCreate(Bundle savedInstanceState) {
+ ...
+
+ buildRowsAdapter();
+}
+
+private void buildRowsAdapter() {
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
+ new StringPresenter());
+ listRowAdapter.add("Media Item 1");
+ listRowAdapter.add("Media Item 2");
+ listRowAdapter.add("Media Item 3");
+ HeaderItem header = new HeaderItem(i, "Category " + i, null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ mBrowseFragment.setAdapter(mRowsAdapter);
+}
+</pre>
+
+<p>This example shows a static implementation of the adapters. A typical media browsing
+ application uses data from an online database or web service. For an example of a browsing
+ application that uses data retrieved from the web, see the <a href="">!FIX</a> code sample.</p>
+
+<p>The following screenshot shows the output of this code on an Android TV device:</p>
+
+<img src="{@docRoot}preview/tv/images/browsefragment.png" alt="" height="XXX" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Display layout example based on the
+ {@link android.support.v17.leanback.app.BrowseFragment} and {@code StringPresenter}
+ classes.
+</p>
+
+
+<h2 id="background">Updating the Background</h2>
+
+<p>In order to add visual interest to a media browsing app on TV, you can update the background
+ image as users browse through content. This technique can make interaction with your app feel more
+ cinematic and enjoyable for users.</p>
+
+<p>The Leanback support library provides a {@link
+ android.support.v17.leanback.app.BackgroundManager} class for changing the background of your TV
+ app activity. The following example shows how to create a simple method for updating the
+ background:</p>
+
+<pre>
+protected void updateBackground(Drawable drawable) {
+ BackgroundManager.getInstance(this).setDrawable(drawable);
+}
+</pre>
+
+<p>Many of the existing media browse apps automatically update the background as the user
+ navigates through media listings. In order to do this, you can set up a selection listener to
+ automatically update the background based on the user's current selection. The following example
+ shows you how to set up an {@link android.support.v17.leanback.widget.OnItemSelectedListener}
+ class to catch selection events and update the background:</p>
+
+<pre>
+protected void clearBackground() {
+ BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
+}
+
+protected OnItemSelectedListener getDefaultItemSelectedListener() {
+ return new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(Object item, Row row) {
+ if (item instanceof Movie ) {
+ URI uri = ((Movie)item).getBackdropURI();
+ updateBackground(uri);
+ } else {
+ clearBackground();
+ }
+ }
+ };
+}
+</pre>
+
+<p class="note">
+ <strong>Note:</strong> The implementation above is a simple example shown for purposes of
+ illustration. When creating this function in your own app, you should consider running the
+ background update action in a separate thread for better performance. In addition, if you are
+ planning on updating the background in response to user's scrolling through items, consider adding
+ a time to delay a background image update until the user settles on item, to avoid excessive
+ background image updates.
+</p>
diff --git a/docs/html/preview/tv/ui/details.jd b/docs/html/preview/tv/ui/details.jd
new file mode 100644
index 0000000..86688d5
--- /dev/null
+++ b/docs/html/preview/tv/ui/details.jd
@@ -0,0 +1,226 @@
+page.title=DetailFragment
+parent.title=User Interfaces for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=BrowseFragment
+previous.link=browse.html
+next.title=Searching in TV Apps
+next.link=in-app-search.html
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#details-presenter">Build a Details Presenter</a></li>
+ <li><a href="#details-fragment">Extend the Details Fragment</a>
+ <li><a href="#activity">Creating a Details Activity</a></li>
+ <li><a href="#item-listener">Listener for Clicked Items</a></li>
+ </li>
+ </ol>
+</div>
+</div>
+
+<p>The media browsing interface classes provided by the leanback support library include classes
+ for displaying additional information about a media item, such as a description or reviews, and
+ taking action on that item, such as purchasing it or playing its content. This section discusses
+ how to create a presenter class for media item details and extend the {@code DetailsFragment}
+ class to implement a details view for a media item when it is selected by a user.</p>
+
+<p class="note">
+ <strong>Note:</strong> The implementation example shown here uses an additional activity to
+ contain the {@code DetailsFragment}. However, it is possible to avoid creating a second activity
+ by replacing the current {@code BrowseFragment} with a {@code DetailsFragment} within the <em>same</em>
+ activity using fragment transactions. For more information on using fragment transactions, see the
+ <a href="{@docRoot}training/basics/fragments/fragment-ui.html#Replace">Building a Dynamic
+ UI with Fragments</a> training.
+</p>
+
+
+<h2 id="details-presenter">Build a Details Presenter</h2>
+
+<p>In the media browsing framework provided for by the leanback support library, you use
+ presenter objects to control the display of data on screen, including media item details. The
+ framework provides the {@code AbstractDetailsDescriptionPresenter} class for this purpose, which
+ is a nearly complete implementation of the presenter for media item details. All you have to do is
+ implement the {@code onBindDescription()} method to bind the view fields to your data objects, as shown in
+ the following code sample:</p>
+
+<pre>
+public class DetailsDescriptionPresenter extends AbstractDetailsDescriptionPresenter {
+
+ @Override
+ protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
+ MyMediaItemDetails details = (MyMediaItemDetails) itemData;
+ // In a production app, the itemData object contains the information
+ // needed to display details for the media item:
+ // viewHolder.getTitle().setText(details.getShortTitle());
+
+ // Here we provide static data for testing purposes:
+ viewHolder.getTitle().setText(itemData.toString());
+ viewHolder.getSubtitle().setText("2014 Drama TV-14");
+ viewHolder.getBody().setText("Lorem ipsum dolor sit amet, consectetur "
+ + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
+ + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
+ + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
+ + "commodo consequat.");
+ }
+}
+</pre>
+
+
+<h2 id="details-fragment">Extend the Details Fragment</h2>
+
+<p>When you use the {@code DetailsFragment} class for displaying your media item details, you
+ extend that class to provide additional content such as a preview image and actions for the media
+ item. You can also provide additional content, such as a list of related media items.</p>
+
+<p>The following example code demonstrates how to use the presenter class you created in the
+ previous section, add a preview image and actions for the media item being viewed. This example
+ also shows the addition of a related media items row, which appears below the details listing.</p>
+
+<pre>
+public class MediaItemDetailsFragment extends DetailsFragment {
+ private static final String TAG = "MediaItemDetailsFragment";
+ private ArrayObjectAdapter mRowsAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ buildDetails();
+ }
+
+ private void buildDetails() {
+ ClassPresenterSelector selector = new ClassPresenterSelector();
+ // Attach your media item details presenter to the row presenter:
+ DetailsOverviewRowPresenter rowPresenter =
+ new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
+
+ selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
+ selector.addClassPresenter(ListRow.class,
+ new ListRowPresenter());
+ mRowsAdapter = new ArrayObjectAdapter(selector);
+
+ Resources res = getActivity().getResources();
+ DetailsOverviewRow detailsOverview = new DetailsOverviewRow(
+ "Media Item Details");
+
+ // Add images and action buttons to the details view
+ detailsOverview.setImageDrawable(res.getDrawable(R.drawable.jelly_beans));
+ detailsOverview.addAction(new Action(1, "Buy $9.99"));
+ detailsOverview.addAction(new Action(2, "Rent $2.99"));
+ mRowsAdapter.add(detailsOverview);
+
+ // Add a Related items row
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
+ new StringPresenter());
+ listRowAdapter.add("Media Item 1");
+ listRowAdapter.add("Media Item 2");
+ listRowAdapter.add("Media Item 3");
+ HeaderItem header = new HeaderItem(0, "Related Items", null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+
+ setAdapter(mRowsAdapter);
+ }
+}
+</pre>
+
+<p>The following screenshot shows the output of this code on a TV device:</p>
+
+<img src="{@docRoot}preview/tv/images/detailsfragment.png" alt="" height="XXX" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Display layout example based on {@code DetailsFragment}, using a
+ {@code DetailsOverviewRow} and a {@code ListRow} for related items.
+</p>
+
+
+<h3 id="activity">Creating a Details Activity</h3>
+
+<p>Fragments such as the {@code DetailsFragment} must be contained within an activity in order
+ to be used for display. Creating an activity for your details view, separate from the browse
+ activity, enables you to invoke your details view using an Intent. This section explains how to
+ build an activity to contain your implementation of the detail view for your media items.</p>
+
+<p>Start creating the details activity by building a layout that references your implementation
+ of the {@code DetailsFragment}:</p>
+
+<pre>
+<!-- file: res/layout/details.xml -->
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ <strong>android:name="com.example.android.mediabrowser.MediaItemDetailsFragment"</strong>
+ android:id="@+id/details_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
+</pre>
+
+<p>Next, create an activity class that uses the layout shown in the previous code example:</p>
+
+<pre>
+public class DetailsActivity extends Activity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ <strong>setContentView(R.layout.details);</strong>
+ }
+}
+</pre>
+
+<p>Finally, add this new activity to the manifest. Remember to apply the Leanback theme to
+ ensure that the user interface is consistent with the media browse activity:</p>
+
+<pre>
+<application>
+ ...
+
+ <activity android:name=".DetailsActivity"
+ android:exported="true"
+ <strong>android:theme="@style/Theme.Leanback"/></strong>
+
+</application>
+</pre>
+
+
+<h3 id="item-listener">Listener for Clicked Items</h3>
+
+<p>After you have implemented the {@code DetailsFragment}, you must modify your main media
+ browsing view to move to your details view when a user clicks on a media item. In order to enable
+ this behavior, add an {@code OnItemClickedListener} object to the BrowseFragment that fires an
+ intent to start the item details activity.</p>
+
+<p>The following example shows how to implement a listener to start the details view when a user
+ clicks a media item in the main media browsing activity:</p>
+
+<pre>
+public class BrowseMediaActivity extends Activity {
+ ...
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ ...
+
+ // create the media item rows
+ buildRowsAdapter();
+
+ // add a listener for selected items
+ mBrowseFragment.setOnItemClickedListener(
+ new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ System.out.println("Media Item clicked: " + item.toString());
+ Intent intent = new Intent(BrowseMediaActivity.this,
+ DetailsActivity.class);
+ // pass the item information
+ intent.getExtras().putLong("id", item.getId());
+ startActivity(intent);
+ }
+ });
+ }
+}
+</pre>
diff --git a/docs/html/preview/tv/ui/in-app-search.jd b/docs/html/preview/tv/ui/in-app-search.jd
new file mode 100644
index 0000000..b372254
--- /dev/null
+++ b/docs/html/preview/tv/ui/in-app-search.jd
@@ -0,0 +1,119 @@
+page.title=Searching in TV Apps
+parent.title=User Interfaces for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=DetailsFragment
+previous.link=details.html
+next.title=Recommendations
+next.link=recommendations.html
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#add-search-ui">Add Search User Interface</a></li>
+ </ol>
+
+</div>
+</div>
+
+
+<p>Users frequently have specific content in mind when using a media app. A search interface can
+ help your users get to the content they want faster than browsing. The Leanback library provides a
+ set of classes to enable a standard search interface within your app that is consistent with other
+ search functions on TV and provides features such as voice input.</p>
+
+<h2 id="add-search-ui">Add Search User Interface</h2>
+<p>When you use the BrowseFragment class for your media browsing interface, you can enable the
+ search icon by setting an OnClickListener to the browse fragment object. The following sample code
+ demonstrates this technique.</p>
+
+<pre>
+@Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.browse_activity);
+
+ mBrowseFragment = (BrowseFragment)
+ getFragmentManager().findFragmentById(R.id.browse_fragment);
+
+ ...
+
+ mBrowseFragment.setOnSearchClickedListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ mBrowseFragment.setAdapter(buildAdapter());
+}
+</pre>
+
+<p class="note">
+ <strong>Note:</strong> You can set the color of the search icon using the
+ {@code setSearchAffordanceColor()} method of {@code BrowseFragment}.
+</p>
+
+<p>When a user selects the search icon, the system invokes a search activity via the defined
+ Intent. Your search activity should use a linear layout containing a SearchFragment. This fragment
+ must also implement the SearchFragment.SearchResultProvider interface in order to display the
+ results of a search. The following code sample shows how to extend the SearchFragment class to
+ provide a search interface and results:</p>
+
+<pre>
+public class MySearchFragment extends SearchFragment
+ implements SearchFragment.SearchResultProvider {
+
+ private static final int SEARCH_DELAY_MS = 300;
+ private ArrayObjectAdapter mRowsAdapter;
+ private Handler mHandler = new Handler();
+ private SearchRunnable mDelayedLoad;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+ setSearchResultProvider(this);
+ setOnItemClickedListener(getDefaultItemClickedListener());
+ mDelayedLoad = new SearchRunnable();
+ }
+
+ @Override
+ public ObjectAdapter getResultsAdapter() {
+ return mRowsAdapter;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newQuery) {
+ mRowsAdapter.clear();
+ if (!TextUtils.isEmpty(newQuery)) {
+ mDelayedLoad.setSearchQuery(newQuery);
+ mHandler.removeCallbacks(mDelayedLoad);
+ mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ mRowsAdapter.clear();
+ if (!TextUtils.isEmpty(query)) {
+ mDelayedLoad.setSearchQuery(query);
+ mHandler.removeCallbacks(mDelayedLoad);
+ mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+ }
+ return true;
+ }
+}
+</pre>
+
+<p>This example code shown above is meant to be used with a separate SearchRunnable class, that
+ runs the search query on a separate thread. This technique keeps potentially slow-running queries
+ from interfering with the main user interface thread.</p>
+
diff --git a/docs/html/preview/tv/ui/index.jd b/docs/html/preview/tv/ui/index.jd
new file mode 100644
index 0000000..9513bc6
--- /dev/null
+++ b/docs/html/preview/tv/ui/index.jd
@@ -0,0 +1,44 @@
+page.title=User Interfaces for TV
+page.tags="input","screens"
+
+trainingnavtop=true
+startpage=true
+
+@jd:body
+
+
+<p>
+ Building an effective and engaging for TV devices requires a firm understanding what works well
+ in the context of a living room. Imagine a large screen that can be seen by many people at the
+ same time, controlled a few buttons by users with limited attention and you start to see the
+ challenges and opportunity of building an app for TV. Building apps for this environment
+ requires a different approach and different tools.</p>
+
+<p>This section discusses how to build a living room experience with your app, including
+ implementation instructions and user interface widgets built for TV. Also check out the
+ <a href="{@docRoot}design/tv/index.html">Design for TV</a> for information and inspiration
+ on creating engaging user interfaces for TV devices.</p>
+
+<h2>Topics</h2>
+
+<dl>
+ <dt><b><a href="layouts.html">Layouts</a></b></dt>
+ <dd>Learn how to build app layouts for TV screens.</dd>
+
+ <dt><b><a href="navigation.html">Navigation</a></b></dt>
+ <dd>Learn how to build navigation for TV devices.</dd>
+
+ <dt><b><a href="browse.html">BrowseFragment</a></b></dt>
+ <dd>Learn how to use this fragment to build a browsing interface for media catalogs.</dd>
+
+ <dt><b><a href="details.html">DetailsFragment</a></b></dt>
+ <dd>Learn how to use this fragment to build a details page for media items.</dd>
+
+ <dt><b><a href="search.html">In-App Search</a></b></dt>
+ <dd>Learn how to use a built-for-TV user interface for searching within your app.</dd>
+
+ <dt><b><a href="recommendations.html">Recommendations</a></b></dt>
+ <dd>Learn how to contribute watch next suggestions and get your content noticed by users.</dd>
+</dl>
+
+
diff --git a/docs/html/training/tv/optimizing-layouts-tv.jd b/docs/html/preview/tv/ui/layouts.jd
similarity index 62%
rename from docs/html/training/tv/optimizing-layouts-tv.jd
rename to docs/html/preview/tv/ui/layouts.jd
index a6db052..0c2448e 100644
--- a/docs/html/training/tv/optimizing-layouts-tv.jd
+++ b/docs/html/preview/tv/ui/layouts.jd
@@ -1,36 +1,30 @@
-page.title=Optimizing Layouts for TV
-parent.title=Designing for TV
+page.title=Layouts for TV
+parent.title=User Interfaces for TV
parent.link=index.html
trainingnavtop=true
-next.title=Optimizing Navigation for TV
-next.link=optimizing-navigation-tv.html
+next.title=Navigation for TV
+next.link=navigation.html
@jd:body
-<div id="tb-wrapper">
-<div id="tb">
-
-<h2>This lesson teaches you to</h2>
-<ol>
- <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
- <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li>
- <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li>
- <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li>
-</ol>
-
-<h2>You should also read</h2>
-<ul>
- <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
-</ul>
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
+ <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li>
+ <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li>
+ <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li>
+ </ol>
</div>
</div>
<p>
-When your application is running on a television set, you should assume that the user is sitting about
-ten feet away from the screen. This user environment is referred to as the
-<a href="http://en.wikipedia.org/wiki/10-foot_user_interface">10-foot UI</a>. To provide your
+When your application is running on a television set, you should assume that the user is sitting about
+ten feet away from the screen. This user environment is referred to as the
+<a href="http://en.wikipedia.org/wiki/10-foot_user_interface">10-foot UI</a>. To provide your
users with a usable and enjoyable experience, you should style and lay out your UI accordingly..
</p>
<p>
@@ -42,25 +36,25 @@
<li>Providing high resolution bitmaps and icons for HD TV screens.</li>
</ul>
-<h2 id="DesignLandscapeLayouts">Design Landscape Layouts</h2>
+<h2 id="DesignLandscapeLayouts">Design Landscape Layouts</h2>
<p>
TV screens are always in landscape orientation. Follow these tips to build landscape layouts optimized for TV screens:
-</p>
+</p>
<ul>
- <li>Put on-screen navigational controls on the left or right side of the screen and save the
+ <li>Put on-screen navigational controls on the left or right side of the screen and save the
vertical space for content.</li>
- <li>Create UIs that are divided into sections, by using <a href="{@docRoot}guide/components/fragments.html">Fragments</a>
- and use view groups like {@link android.widget.GridView} instead
- of {@link android.widget.ListView} to make better use of the
+ <li>Create UIs that are divided into sections, by using <a href="{@docRoot}guide/components/fragments.html">Fragments</a>
+ and use view groups like {@link android.widget.GridView} instead
+ of {@link android.widget.ListView} to make better use of the
horizontal screen space.</li>
- <li>Use view groups such as {@link android.widget.RelativeLayout}
- or {@link android.widget.LinearLayout} to arrange views.
- This allows the Android system to adjust the position of the views to the size, alignment,
+ <li>Use view groups such as {@link android.widget.RelativeLayout}
+ or {@link android.widget.LinearLayout} to arrange views.
+ This allows the Android system to adjust the position of the views to the size, alignment,
aspect ratio, and pixel density of the TV screen.</li>
<li>Add sufficient margins between layout controls to avoid a cluttered UI.</li>
-</ul>
-
+</ul>
+
<p>
For example, the following layout is optimized for TV:
</p>
@@ -68,12 +62,12 @@
<img src="{@docRoot}images/training/panoramio-grid.png" />
<p>
-In this layout, the controls are on the lefthand side. The UI is displayed within a
+In this layout, the controls are on the lefthand side. The UI is displayed within a
{@link android.widget.GridView}, which is well-suited to landscape orientation.
-In this layout both GridView and Fragment have the width and height set
+In this layout both GridView and Fragment have the width and height set
dynamically, so they can adjust to the screen resolution. Controls are added to the left side Fragment programatically at runtime.
The layout file for this UI is {@code res/layout-land-large/photogrid_tv.xml}.
-(This layout file is placed in {@code layout-land-large} because TVs have large screens with landscape orientation. For details refer to
+(This layout file is placed in {@code layout-land-large} because TVs have large screens with landscape orientation. For details refer to
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.)</p>
res/layout-land-large/photogrid_tv.xml
@@ -88,7 +82,7 @@
android:layout_marginLeft="5dip"
android:layout_height="match_parent" />
- <GridView
+ <GridView
android:id="@+id/gridview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
@@ -99,7 +93,7 @@
<p>
To set up action bar items on the left side of the screen, you can also include the <a
href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarLibrary">
-Left navigation bar library</a> in your application to set up action items on the left side
+Left navigation bar library</a> in your application to set up action items on the left side
of the screen, instead of creating a custom Fragment to add controls:
</p>
@@ -108,9 +102,9 @@
</pre>
<p>
-When you have an activity in which the content scrolls vertically, always use a left navigation bar;
-otherwise, your users have to scroll to the top of the content to switch between the content view and
-the ActionBar. Look at the
+When you have an activity in which the content scrolls vertically, always use a left navigation bar;
+otherwise, your users have to scroll to the top of the content to switch between the content view and
+the ActionBar. Look at the
<a href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarDemo">
Left navigation bar sample app</a> to see how to simple it is to include the left navigation bar in your app.
</p>
@@ -124,7 +118,7 @@
<ul>
<li>Break text into small chunks that users can quickly scan.</li>
<li>Use light text on a dark background. This style is easier to read on a TV.</li>
- <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes. Use simple sans-serif
+ <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes. Use simple sans-serif
fonts and use anti-aliasing to increase readability.</li>
<li>Use Android's standard font sizes:
<pre>
@@ -136,10 +130,10 @@
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</pre></li>
- <li>Ensure that all your view widgets are large enough to be clearly visible to someone sitting 10 feet away
- from the screen (this distance is greater for very large screens). The best way to do this is to use
- layout-relative sizing rather than absolute sizing, and density-independent pixel units instead of absolute
- pixel units. For example, to set the width of a widget, use wrap_content instead of a pixel measurement,
+ <li>Ensure that all your view widgets are large enough to be clearly visible to someone sitting 10 feet away
+ from the screen (this distance is greater for very large screens). The best way to do this is to use
+ layout-relative sizing rather than absolute sizing, and density-independent pixel units instead of absolute
+ pixel units. For example, to set the width of a widget, use wrap_content instead of a pixel measurement,
and to set the margin for a widget, use dip instead of px values.
</li>
</ul>
@@ -150,17 +144,17 @@
<h2 id="DesignForLargeScreens">Design for High-Density Large Screens</h2>
<p>
-The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then
-allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels)
-does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades
+The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then
+allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels)
+does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades
UI quality).
</p>
<p>
To get the best scaling results for images, provide them as <a href="{@docRoot}tools/help/draw9patch.html">
9-patch image</a> elements if possible.
-If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This
-is not a good experience for the user. Instead, use high-quality images.
+If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This
+is not a good experience for the user. Instead, use high-quality images.
</p>
<p>
@@ -171,40 +165,40 @@
<h2 id="HandleLargeBitmaps">Design to Handle Large Bitmaps</h2>
<p>
-The Android system has a limited amount of memory, so downloading and storing high-resolution images can often
+The Android system has a limited amount of memory, so downloading and storing high-resolution images can often
cause out-of-memory errors in your app. To avoid this, follow these tips:
</p>
<ul>
- <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in
- a {@link android.widget.GridView} or
- {@link android.widget.Gallery}, only load an image when
- {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()}
+ <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in
+ a {@link android.widget.GridView} or
+ {@link android.widget.Gallery}, only load an image when
+ {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()}
is called on the View's {@link android.widget.Adapter}.
</li>
- <li>Call {@link android.graphics.Bitmap#recycle()} on
+ <li>Call {@link android.graphics.Bitmap#recycle()} on
{@link android.graphics.Bitmap} views that are no longer needed.
</li>
- <li>Use {@link java.lang.ref.WeakReference} for storing references
- to {@link android.graphics.Bitmap} objects in an in-memory
+ <li>Use {@link java.lang.ref.WeakReference} for storing references
+ to {@link android.graphics.Bitmap} objects in an in-memory
{@link java.util.Collection}.</li>
- <li>If you fetch images from the network, use {@link android.os.AsyncTask}
+ <li>If you fetch images from the network, use {@link android.os.AsyncTask}
to fetch them and store them on the SD card for faster access.
Never do network transactions on the application's UI thread.
</li>
- <li>Scale down really large images to a more appropriate size as you download them; otherwise, downloading the image
+ <li>Scale down really large images to a more appropriate size as you download them; otherwise, downloading the image
itself may cause an "Out of Memory" exception. Here is sample code that scales down images while downloading:
-
+
<pre>
// Get the source image's dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
// This does not download the actual image, just downloads headers.
- options.inJustDecodeBounds = true;
+ options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
// The actual width of the image.
- int srcWidth = options.outWidth;
+ int srcWidth = options.outWidth;
// The actual height of the image.
- int srcHeight = options.outHeight;
+ int srcHeight = options.outHeight;
// Only scale if the source is bigger than the width of the destination view.
if(desiredWidth > srcWidth)
@@ -227,8 +221,8 @@
options.inScaled = false;
// Ensures the image stays as a 32-bit ARGB_8888 image.
// This preserves image quality.
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+
Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
// Resize
@@ -243,4 +237,64 @@
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
scaledBitmap = null;
</pre>
- </li> </ul>
\ No newline at end of file
+ </li> </ul>
+
+
+<h2>Themes and Layouts</h2>
+
+<p>
+ In general, layouts shown in the context of TV devices must be built to be simpler and less
+ demanding of the user. The <a href="{@docRoot}design/tv/index.html">TV Style Guide</a> provides
+ more guidance on how to design an effective app for TV use.
+</p>
+
+<p>Here are some common Android user interface elements that you should specifically NOT use for
+ a TV interface:</p>
+
+<ul>
+ <li><strong>ActionBar</strong> - While this user interface convention is recommended for use
+ on phones and tablets, it is not appropriate for a TV interface. In particular, using an
+ ActionBar options menu (or any pull-down menu for that matter) is strongly discouraged, due to
+ the difficulty in navigating such a menu with a remote control.</li>
+ <li><strong>ViewPager</strong> - Sliding between screens can work great on a phone or tablet,
+ but don't try this on a TV!</li>
+</ul>
+
+
+<h2>Leanback Theme</h2>
+
+<p>The Android framework provides a standard Leanback theme for TV activities, which establishes
+ a consistent visual style for TV apps. Use of this theme is recommended for most apps. The
+ following code sample shows how to apply this theme to a given activity within an app:</p>
+<pre>
+<activity
+ android:name="com.example.android.TvActivity"
+ android:label="@string/app_name"
+ <strong>android:theme="@android:style/Theme.Leanback"</strong>>
+</pre>
+
+<p>
+ <strong>Note:</strong> If you do not using the Leanback theme for your TV activities, apply
+ Theme.NoTitleBar to your TV activities to suppress display of an app title bar.
+</p>
+
+
+<h2>Overscan and Layouts</h2>
+
+<p>Application layouts for TV have some unique requirements due to the evolution of TV
+ standards. In short, items placed on the edge of a layout may be cut short or not displayed at all
+ due to TV manufacturers implementation of overscan.</p>
+
+<p>
+ In order to make sure that all the user interface elements you place in a layout are actually
+ shown on screen, you should incorporate a 10% margin on all sides of your layout. This translates
+ into a 27dp margin on the left and right edges and a 48dp margin on the top and bottom of your
+ base layouts for activities. For more information on designing for TV overscan, see the
+ <a href="{@docRoot}design/tv/index.html">TV Style Guide</a>.
+</p>
+
+<p class="caution">
+ <strong>Caution:</strong> Do not apply overscan margins to your layout if you are using the
+ leanback BrowseFragment or other leanback Fragment widgets, as those layouts already incorporate
+ overscan-safe margins.
+</p>
diff --git a/docs/html/preview/tv/ui/navigation.jd b/docs/html/preview/tv/ui/navigation.jd
new file mode 100644
index 0000000..f91ae38
--- /dev/null
+++ b/docs/html/preview/tv/ui/navigation.jd
@@ -0,0 +1,197 @@
+page.title=Navigation for TV
+parent.title=User Interfaces for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Layouts for TV
+previous.link=layouts.html
+next.title=BrowseFragment
+next.link=browse.html
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#HandleDpadNavigation">D-pad Navigation</a></li>
+ <li><a href="#HandleFocusSelection">Visual Indications for Focus and Selection</a></li>
+ <li><a href="#DesignForEasyNavigation">Easy Navigation</a></li>
+ </ol>
+
+</div>
+</div>
+
+<p>An important aspect of the user experience when operating a TV is the direct human interface:
+ a remote control. As you optimize your Android application for TVs, you should pay special
+ attention to how the user actually navigates around your application when using a remote control
+ instead of a touch screen.</p>
+
+<p>This lesson shows you how to optimize navigation for TV by:</p>
+
+<ul>
+ <li>Ensuring all layout controls are D-pad navigable</li>
+ <li>Providing clear feedback for UI navigation</li>
+ <li>Placing layout controls for easy access</li>
+</ul>
+
+
+<h2 id="HandleDpadNavigation">D-pad Navigation</h2>
+
+<p>On a TV, users navigate with controls on a TV remote, using either a D-pad or arrow keys.
+ This limits movement to up, down, left, and right. To build a great TV-optimized app, you must
+ provide a navigation scheme in which the user can quickly learn how to navigate your app using the
+ remote.</p>
+
+<p>
+When you design navigation for D-pad, follow these guidelines:
+</p>
+
+<ul>
+ <li>Ensure that the D-pad can navigate to all the visible controls on the screen.</li>
+ <li>For scrolling lists with focus, D-pad up/down keys scroll the list and Enter key selects
+ an item in the list. Ensure that users can select an element in the list and that the list still
+ scrolls when an element is selected.</li>
+ <li>Ensure that movement between controls is straightforward and predictable.</li>
+</ul>
+
+<p>Android usually handles navigation order between layout elements automatically, so you don't
+ need to do anything extra. If the screen layout makes navigation difficult, or if you want users
+ to move through the layout in a specific way, you can set up explicit navigation for your
+ controls. For example, for an {@code android.widget.EditText}, to define the next control to
+ receive focus, use:</p>
+
+<pre>
+<EditText android:id="@+id/LastNameField"
+ android:nextFocusDown="@+id/FirstNameField"\>
+</pre>
+
+<p>The following table lists all of the available navigation attributes:</p>
+
+<table>
+ <tr>
+ <th>Attribute</th>
+ <th>Function</th>
+ </tr>
+ <tr>
+ <td>{@link android.R.attr#nextFocusDown}</td>
+ <td>Defines the next view to receive focus when the user navigates down.</td>
+ </tr>
+ <tr>
+ <td>{@link android.R.attr#nextFocusLeft}</td>
+ <td>Defines the next view to receive focus when the user navigates left.</td>
+ </tr>
+ <tr>
+ <td>{@link android.R.attr#nextFocusRight}</td>
+ <td>Defines the next view to receive focus when the user navigates right.</td>
+ </tr>
+ <tr>
+ <td>{@link android.R.attr#nextFocusUp}</td>
+ <td>Defines the next view to receive focus when the user navigates up.</td>
+ </tr>
+</table>
+
+<p>To use one of these explicit navigation attributes, set the value to the ID (android:id
+ value) of another widget in the layout. You should set up the navigation order as a loop, so that
+ the last control directs focus back to the first one.</p>
+
+<p class="note">
+ <strong>Note:</strong> You should only use these attributes to modify the navigation order if the
+ default order that the system applies does not work well.
+</p>
+
+
+<h2 id="HandleFocusSelection">Visual Indications for Focus and Selection</h2>
+
+<p>Use appropriate color highlights for all navigable and selectable elements in the UI. This makes
+ it easy for users to know whether the control is currently focused or selected when they navigate
+ with a D-pad. Also, use uniform highlight scheme across your application.</p>
+
+<p>
+Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">Drawable State List Resources</a> to implement highlights
+for selected and focused controls. For example:
+</p>
+
+res/drawable/button.xml:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/button_pressed" /> <!-- pressed -->
+ <item android:state_focused="true"
+ android:drawable="@drawable/button_focused" /> <!-- focused -->
+ <item android:state_hovered="true"
+ android:drawable="@drawable/button_focused" /> <!-- hovered -->
+ <item android:drawable="@drawable/button_normal" /> <!-- default -->
+</selector>
+</pre>
+
+<p>
+This layout XML applies the above state list drawable to a {@link android.widget.Button}:
+</p>
+<pre>
+<Button
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:background="@drawable/button" />
+</pre>
+
+<p>Provide sufficient padding within the focusable and selectable controls so that the
+ highlights around them are clearly visible.</p>
+
+
+<h2 id="DesignForEasyNavigation">Design for Easy Navigation</h2>
+
+<p>Users should be able to navigate to any UI control with a couple of D-pad clicks. Navigation
+ should be easy and intuitive to understand. For any non-intuitive actions, provide users with
+ written help, using a dialog triggered by a help button or action bar icon.</p>
+
+<p>Predict the next screen that the user will want to navigate to and provide one click
+ navigation to it. If the current screen UI is very sparse, consider making it a multi pane screen.
+ Use fragments for making multi-pane screens. For example, consider the multi-pane UI below with
+ continent names on the left and list of cool places in each continent on the right.</p>
+
+<img src="{@docRoot}images/training/cool-places.png" alt="" />
+
+<p>The above UI consists of three fragments - <code>left_side_action_controls</code>,
+ <code>continents</code>, and <code>places</code> - as shown in its layout xml file below.
+ Such multi-pane UIs make D-pad navigation easier and make good use of the horizontal screen
+ space for TVs.
+</p>
+
+<pre>
+<!-- res/layout/cool_places.xml -->
+
+<LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ >
+ <fragment
+ android:id="@+id/left_side_action_controls"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dip"
+ android:layout_weight="0.2"/>
+ <fragment
+ android:id="@+id/continents"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dip"
+ android:layout_weight="0.2"/>
+
+ <fragment
+ android:id="@+id/places"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dip"
+ android:layout_weight="0.6"/>
+
+</LinearLayout>
+</pre>
+
+<p>Also, notice in the UI layout above action controls are on the left hand side of a vertically
+ scrolling list to make them easily accessible using D-pad. In general, for layouts with
+ horizontally scrolling components, place action controls on left or right hand side and vice versa
+ for vertically scrolling components.</p>
+
diff --git a/docs/html/preview/tv/ui/recommendations.jd b/docs/html/preview/tv/ui/recommendations.jd
new file mode 100644
index 0000000..52ac2e5
--- /dev/null
+++ b/docs/html/preview/tv/ui/recommendations.jd
@@ -0,0 +1,234 @@
+page.title=Making Recommendations
+parent.title=User Interfaces for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Searching in TV Apps
+previous.link=in-app-search.html
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#service">Create a Recommendations Service</a></li>
+ <li><a href="#build">Build Recommendations</a></li>
+ <li><a href="#run-service">Run Recommendations Service</a></li>
+ <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
+ </ol>
+
+</div>
+</div>
+
+
+<p>Content recommendations appear as the first row of the TV launch screen after the first use
+ of the device. This row is intended to help users quickly find content they enjoy. Contributing
+ recommendations from your apps content catalog can help bring users back to your app.</p>
+
+
+<img src="{@docRoot}preview/tv/images/home-recommendations.png" alt="" height="XXX" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> The first row after the search widget is the system-wide
+ recommendations.
+</p>
+
+
+<h2 id="service">Create a Recommendations Service</h2>
+
+<p>Content recommendations are created with background processing. In order for your application
+ to contribute to recommendations, you create a service that periodically adds listings from your
+ app's catalog to the system list of recommendations.</p>
+
+<p>The following code example illustrates how to extend the {@link android.app.IntentService} to
+ create a recommendation service for your application.</p>
+
+<pre>
+public class RecommendationsService extends IntentService {
+
+ ...
+
+ public Notification buildRecommendation(Context context, Movie movie)
+ throws IOException {
+
+ if (mNotificationManager == null) {
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ Bundle extras = new Bundle();
+ if (mBackgroundUri != movie.getBackgroundUri()) {
+ extras.putString(EXTRA_BACKGROUND_IMAGE_URL, movie.getBackgroundUri());
+ }
+
+ // build the recommendation as a Notification object
+ Notification notification = new NotificationCompat.BigPictureStyle(
+ new NotificationCompat.Builder(context)
+ .setContentTitle(movie.getTitle())
+ .setContentText(movie.getDescription())
+ .setPriority(movie.getPriority())
+ .setOngoing(true)
+ .setCategory("recommendation")
+ .setLargeIcon(movie.getImage())
+ .setSmallIcon(movie.getSmallIcon())
+ .setContentIntent(buildPendingIntent(movie.getId()))
+ .setExtras(extras))
+ .build();
+
+ // post the recommendation to the NotificationManager
+ mNotificationManager.notify(movie.getId(), notification);
+ mNotificationManager = null;
+ return notification;
+ }
+
+ private PendingIntent buildPendingIntent(long id) {
+ Intent detailsIntent = new Intent(this, DetailsActivity.class);
+ detailsIntent.putExtra("id", id);
+
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+ stackBuilder.addParentStack(DetailsActivity.class);
+ stackBuilder.addNextIntent(detailsIntent);
+ // Ensure each PendingIntent is unique
+ detailsIntent.setAction(Long.toString(id));
+
+ PendingIntent intent = stackBuilder.getPendingIntent(
+ 0, PendingIntent.FLAG_UPDATE_CURRENT);
+ return intent;
+ }
+}
+</pre>
+
+<p>In order for this class to be recognized and run as a service, you must register this service
+ using your app manifest. The following code snippet illustrates how to add this class as a
+ service:</p>
+
+<pre>
+<manifest ... >
+ <application ... >
+ ...
+
+ <service android:name=".UpdateRecommendationsService"
+ android:enabled="true" android:exported="true"/>
+ </application>
+</manifest>
+</pre>
+
+<h2 id="build">Build Recommendations</h2>
+
+<p>Once it starts running, your service must create recommendations and pass them to the Android
+ framework. The framework receives the recommendations as {@link android.app.Notification} objects
+ that use a specific style and are marked with a specific category.</p>
+
+<p>The following code example demonstrates how to get an instance of the {@link
+ android.app.NotificationManager}, build a recommendation and post it to the manager:</p>
+
+<pre>
+public class RecommendationsService extends IntentService {
+
+ ...
+
+ public Notification buildRecommendation(Context context, Movie movie)
+ throws IOException {
+
+ if (mNotificationManager == null) {
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ Bundle extras = new Bundle();
+ if (mBackgroundUri != movie.getBackgroundUri()) {
+ extras.putString(EXTRA_BACKGROUND_IMAGE_URL, movie.getBackgroundUri());
+ }
+
+ // build the recommendation as a Notification object
+ Notification notification = new NotificationCompat.BigPictureStyle(
+ new NotificationCompat.Builder(context)
+ .setContentTitle(movie.getTitle())
+ .setContentText(movie.getDescription())
+ .setPriority(movie.getPriority())
+ .setOngoing(true)
+ .setCategory("recommendation")
+ .setLargeIcon(movie.getImage())
+ .setSmallIcon(movie.getSmallIcon())
+ .setContentIntent(buildPendingIntent(movie.getId()))
+ .setExtras(extras))
+ .build();
+
+ // post the recommendation to the NotificationManager
+ mNotificationManager.notify(movie.getId(), notification);
+ mNotificationManager = null;
+ return notification;
+ }
+
+ private PendingIntent buildPendingIntent(long id) {
+ Intent detailsIntent = new Intent(this, DetailsActivity.class);
+ detailsIntent.putExtra("id", id);
+
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+ stackBuilder.addParentStack(DetailsActivity.class);
+ stackBuilder.addNextIntent(detailsIntent);
+ // Ensure each PendingIntent is unique
+ detailsIntent.setAction(Long.toString(id));
+
+ PendingIntent intent = stackBuilder.getPendingIntent(
+ 0, PendingIntent.FLAG_UPDATE_CURRENT);
+ return intent;
+ }
+}
+</pre>
+
+
+<h3 id="run-service">Run Recommendations Service</h3>
+
+<p>Your app's recommendation service must run periodically in order to create current
+ recommendations. In order to run your service, you should create a class that runs a timer and
+ invokes it at regular intervals. The following code example extends the {@link
+ android.content.BroadcastReceiver} class to start periodic execution of a recommendation service
+ every 30 minutes:</p>
+
+<pre>
+public class BootupActivity extends BroadcastReceiver {
+ private static final String TAG = "BootupActivity";
+
+ private static final long INITIAL_DELAY = 5000;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
+ scheduleRecommendationUpdate(context);
+ }
+ }
+
+ private void scheduleRecommendationUpdate(Context context) {
+ AlarmManager alarmManager = (AlarmManager)context.getSystemService(
+ Context.ALARM_SERVICE);
+ Intent recommendationIntent = new Intent(context,
+ UpdateRecommendationsService.class);
+ PendingIntent alarmIntent = PendingIntent.getService(context, 0,
+ recommendationIntent, 0);
+
+ alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ INITIAL_DELAY,
+ AlarmManager.INTERVAL_HALF_HOUR,
+ alarmIntent);
+ }
+}
+</pre>
+
+<p>In order for the {@link android.content.BroadcastReceiver} class to execute after an TV
+ device starts up, you must register this class in your app manifest and attach an intent filter
+ for the completion of the device boot process. This sample code demonstrates how to add this
+ configuration to the manifest:</p>
+
+<pre>
+<manifest ... >
+ <application ... >
+ <receiver android:name=".BootupActivity" android:enabled="true"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
+ </application>
+</manifest>
+</pre>
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
deleted file mode 100644
index 54f7016..0000000
--- a/docs/html/training/tv/index.jd
+++ /dev/null
@@ -1,59 +0,0 @@
-page.title=Designing for TV
-page.tags="input","screens"
-
-trainingnavtop=true
-startpage=true
-
-@jd:body
-
-<div id="tb-wrapper">
-<div id="tb">
-
-<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
-<h2>Dependencies and prerequisites</h2>
-<ul>
- <li>Android 2.0 (API Level 5) or higher</li>
-</ul>
-
-</div>
-</div>
-
-<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=zsRnRLh-O34">
-<div>
- <h3>Video</h3>
- <p>DevBytes: Design for Large Displays - Part 1</p>
-</div>
-</a>
-
-<p>
- Smart TVs powered by Android bring your favorite Android apps to the best screen in your house.
- Thousands of apps in the Google Play Store are already optimized for TVs. This class shows how
- you can optimize your Android app for TVs, including how to build a layout that
- works great when the user is ten feet away and navigating with a remote control.
-</p>
-
-<h2>Lessons</h2>
-
-<dl>
- <dt><b><a href="optimizing-layouts-tv.html">Optimizing Layouts for TV</a></b></dt>
- <dd>Shows you how to optimize app layouts for TV screens, which have some unique characteristics such as:
- <ul>
- <li>permanent "landscape" mode</li>
- <li>high-resolution displays</li>
- <li>"10 foot UI" environment.</li>
- </ul>
- </dd>
-
- <dt><b><a href="optimizing-navigation-tv.html">Optimizing Navigation for TV</a></b></dt>
- <dd>Shows you how to design navigation for TVs, including:
- <ul>
- <li>handling D-pad navigation</li>
- <li>providing navigational feedback</li>
- <li>providing easily-accessible controls on the screen.</li>
- </ul>
- </dd>
-
- <dt><b><a href="unsupported-features-tv.html">Handling features not supported on TV</a></b></dt>
- <dd>Lists the hardware features that are usually not available on TVs. This lesson also shows you how to
- provide alternatives for missing features or check for missing features and disable code at run time.</dd>
-</dl>
diff --git a/docs/html/training/tv/optimizing-navigation-tv.jd b/docs/html/training/tv/optimizing-navigation-tv.jd
deleted file mode 100644
index bb78258..0000000
--- a/docs/html/training/tv/optimizing-navigation-tv.jd
+++ /dev/null
@@ -1,206 +0,0 @@
-page.title=Optimizing Navigation for TV
-parent.title=Designing for TV
-parent.link=index.html
-
-trainingnavtop=true
-previous.title=Optimizing Layouts for TV
-previous.link=optimizing-layouts-tv.html
-next.title=Handling Features Not Supported on TV
-next.link=unsupported-features-tv.html
-
-@jd:body
-
-<div id="tb-wrapper">
-<div id="tb">
-
-<h2>This lesson teaches you to</h2>
-<ol>
- <li><a href="#HandleDpadNavigation">Handle D-pad Navigation</a></li>
- <li><a href="#HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</a></li>
- <li><a href="#DesignForEasyNavigation">Design for Easy Navigation</a></li>
-</ol>
-
-<h2>You should also read</h2>
-<ul>
- <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
-</ul>
-
-</div>
-</div>
-
-<p>
-An important aspect of the user experience when operating a TV is the direct human interface: a remote control.
-As you optimize your Android application for TVs, you should pay special attention to how the user actually navigates
-around your application when using a remote control instead of a touchscreen.
-</p>
-<p>
-This lesson shows you how to optimize navigation for TV by:
-</p>
-
-<ul>
- <li>Ensuring all layout controls are D-pad navigable.</li>
- <li>Providing highly obvious feedback for UI navigation.</li>
- <li>Placing layout controls for easy access.</li>
-</ul>
-
-<h2 id="HandleDpadNavigation">Handle D-pad Navigation</h2>
-
-<p>
-On a TV, users navigate with controls on a TV remote, using either a D-pad or arrow keys.
-This limits movement to up, down, left, and right.
-To build a great TV-optimized app, you must provide a navigation scheme in which the user can
-quickly learn how to navigate your app using the remote.
-</p>
-
-<p>
-When you design navigation for D-pad, follow these guidelines:
-</p>
-
-<ul>
- <li>Ensure that the D-pad can navigate to all the visible controls on the screen.</li>
- <li>For scrolling lists with focus, D-pad up/down keys scroll the list and Enter key selects an item in the list. Ensure that users can
- select an element in the list and that the list still scrolls when an element is selected.</li>
- <li>Ensure that movement between controls is straightforward and predictable.</li>
-</ul>
-
-<p>
-Android usually handles navigation order between layout elements automatically, so you don't need to do anything extra. If the screen layout
-makes navigation difficult, or if you want users to move through the layout in a specific way, you can set up explicit navigation for your
-controls.
-For example, for an {@code android.widget.EditText}, to define the next control to receive focus, use:
-<pre>
-<EditText android:id="@+id/LastNameField" android:nextFocusDown="@+id/FirstNameField"\>
-</pre>
-The following table lists all of the available navigation attributes:
-</p>
-
-<table>
-<tr>
-<th>Attribute</th>
-<th>Function</th>
-</tr>
-<tr>
-<td>{@link android.R.attr#nextFocusDown}</td>
-<td>Defines the next view to receive focus when the user navigates down.</td>
-</tr>
-<tr>
-<td>{@link android.R.attr#nextFocusLeft}</td>
-<td>Defines the next view to receive focus when the user navigates left.</td>
-</tr>
-<tr>
-<td>{@link android.R.attr#nextFocusRight}</td>
-<td>Defines the next view to receive focus when the user navigates right.</td>
-</tr>
-<tr>
-<td>{@link android.R.attr#nextFocusUp}</td>
-<td>Defines the next view to receive focus when the user navigates up.</td>
-</tr>
-</table>
-
-<p>
-To use one of these explicit navigation attributes, set the value to the ID (android:id value) of another widget in the layout. You should set
-up the navigation order as a loop, so that the last control directs focus back to the first one.
-</p>
-
-<p>
-Note: You should only use these attributes to modify the navigation order if the default order that the system applies does not work well.
-</p>
-
-<h2 id="HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</h2>
-
-<p>
-Use appropriate color highlights for all navigable and selectable elements in the UI. This makes it easy for users to know whether the control
-is currently focused or selected when they navigate with a D-pad. Also, use uniform highlight scheme across your application.
-</p>
-
-<p>
-Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">Drawable State List Resources</a> to implement highlights
-for selected and focused controls. For example:
-</p>
-
-res/drawable/button.xml:
-<pre>
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true"
- android:drawable="@drawable/button_pressed" /> <!-- pressed -->
- <item android:state_focused="true"
- android:drawable="@drawable/button_focused" /> <!-- focused -->
- <item android:state_hovered="true"
- android:drawable="@drawable/button_focused" /> <!-- hovered -->
- <item android:drawable="@drawable/button_normal" /> <!-- default -->
-</selector>
-</pre>
-
-<p>
-This layout XML applies the above state list drawable to a {@link android.widget.Button}:
-</p>
-<pre>
-<Button
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:background="@drawable/button" />
-</pre>
-
-<p>
-Provide sufficient padding within the focusable and selectable controls so that the highlights around them are clearly visible.
-</p>
-
-<h2 id="DesignForEasyNavigation">Design for Easy Navigation</h2>
-
-<p>
-Users should be able to navigate to any UI control with a couple of D-pad clicks. Navigation should be easy and intuitive to
-understand. For any non-intuitive actions, provide users with written help, using a dialog triggered by a help button or action bar icon.
-</p>
-
-<p>
-Predict the next screen that the user will want to navigate to and provide one click navigation to it. If the current screen UI is very sparse,
-consider making it a multi pane screen. Use fragments for making multi-pane screens. For example, consider the multi-pane UI below with continent names
-on the left and list of cool places in each continent on the right.
-</p>
-
-<img src="{@docRoot}images/training/cool-places.png" alt="" />
-
-<p>
-The above UI consists of three Fragments - <code>left_side_action_controls</code>, <code>continents</code> and
-<code>places</code> - as shown in its layout
-xml file below. Such multi-pane UIs make D-pad navigation easier and make good use of the horizontal screen space for
-TVs.
-</p>
-res/layout/cool_places.xml
-<pre>
-<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- >
- <fragment
- android:id="@+id/left_side_action_controls"
- android:layout_width="0px"
- android:layout_height="match_parent"
- android:layout_marginLeft="10dip"
- android:layout_weight="0.2"/>
- <fragment
- android:id="@+id/continents"
- android:layout_width="0px"
- android:layout_height="match_parent"
- android:layout_marginLeft="10dip"
- android:layout_weight="0.2"/>
-
- <fragment
- android:id="@+id/places"
- android:layout_width="0px"
- android:layout_height="match_parent"
- android:layout_marginLeft="10dip"
- android:layout_weight="0.6"/>
-
-</LinearLayout>
-</pre>
-
-<p>
-Also, notice in the UI layout above action controls are on the left hand side of a vertically scrolling list to make
-them easily accessible using D-pad.
-In general, for layouts with horizontally scrolling components, place action controls on left or right hand side and
-vice versa for vertically scrolling components.
-</p>
-