blob: 52ac2e5ad8fef586adba4542c104a1c3a2841f42 [file] [log] [blame]
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>
&lt;manifest ... &gt;
&lt;application ... &gt;
...
&lt;service android:name=&quot;.UpdateRecommendationsService&quot;
android:enabled=&quot;true&quot; android:exported=&quot;true&quot;/&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</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;
&#64;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>
&lt;manifest ... &gt;
&lt;application ... &gt;
&lt;receiver android:name=&quot;.BootupActivity&quot; android:enabled=&quot;true&quot;
android:exported=&quot;false&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;/&gt;
&lt;/intent-filter&gt;
&lt;/receiver&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</pre>