summaryrefslogtreecommitdiffstats
path: root/docs/html/preview/tv/ui/recommendations.jd
blob: 2c78064ea4cccf832c9b872ba3e37e1a91282271 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
page.title=Making Recommendations

@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="" id="figure1" />
<p class="img-caption">
  <strong>Figure 1.</strong> An example of the recommendations row.
</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 {
    private static final int MAX_RECOMMENDATIONS = 3;

    public RecommendationsService() {
        super("RecommendationService");
    }

    &#64;Override
    protected void onHandleIntent(Intent intent) {
        MovieDatabase database = MovieDatabase.instance(getApplicationContext());
        List<Movie> recommendations = database.recommendations();

        int count = 0;

        try {
            for (Movie movie : recommendations) {
                // build the individual content recommendations
                buildRecommendation(getApplicationContext(), movie);

                if (++count >= MAX_RECOMMENDATIONS) {
                    break;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Unable to update recommendation", e);
        }
    }
}
</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;.RecommendationsService&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 12 hours:</p>

<pre>
public class BootupReceiver 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_DAY,
                alarmIntent);
    }
}
</pre>

<p>In order for the {@link android.content.BroadcastReceiver} class to execute after a TV
  device starts up, you must register this class in your app manifest and attach an intent filter
  in order for the device boot process to complete. 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;.BootupReceiver&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>

<p class="important">
  <strong>Important:</strong> Receiving a boot completed notification requires that your app
  request the {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission.
  For more information, see {@link android.content.Intent#ACTION_BOOT_COMPLETED}.
</p>