Home | History | Annotate | Download | only in discovery
      1 page.title=Recommending TV Content
      2 page.tags="recommendation","recommend"
      3 
      4 trainingnavtop=true
      5 
      6 @jd:body
      7 
      8 <div id="tb-wrapper">
      9 <div id="tb">
     10   <h2>This lesson teaches you to</h2>
     11   <ol>
     12     <li><a href="#service">Create a Recommendations Service</a></li>
     13     <li><a href="#build">Build Recommendations</a></li>
     14     <li><a href="#run-service">Run Recommendations Service</a></li>
     15   </ol>
     16 </div>
     17 </div>
     18 
     19 <p>
     20   When interacting with TVs, users generally prefer to give minimal input before watching
     21   content. An ideal scenario for many TV users is: sit down, turn on, and watch. The fewest steps
     22   to get users to content they enjoy is generally the path they prefer.
     23 </p>
     24 
     25 <p>
     26   The Android framework assists with minimum-input interaction by providing a recommendations row
     27   on the home screen. Content recommendations appear as the first row of the TV launch screen after
     28   the first use of the device. Contributing recommendations from your app's content catalog can help
     29   bring users back to your app.
     30 </p>
     31 
     32 <img src="{@docRoot}images/tv/home-recommendations.png" alt="" id="figure1" />
     33 <p class="img-caption">
     34   <strong>Figure 1.</strong> An example of the recommendations row.
     35 </p>
     36 
     37 <p>
     38   This lesson teaches you how to create recommendations and provide them to the Android framework
     39   so your app content can be easily discovered and enjoyed by users.
     40 </p>
     41 
     42 
     43 <h2 id="service">Create a Recommendations Service</h2>
     44 
     45 <p>
     46   Content recommendations are created with background processing. In order for your application to
     47   contribute to recommendations, create a service that periodically adds listings from your
     48   app's catalog to the system list of recommendations.
     49 </p>
     50 
     51 <p>
     52   The following code example illustrates how to extend {@link android.app.IntentService} to
     53   create a recommendation service for your application:
     54 </p>
     55 
     56 <pre>
     57 public class RecommendationsService extends IntentService {
     58     private static final int MAX_RECOMMENDATIONS = 3;
     59 
     60     public RecommendationsService() {
     61         super("RecommendationService");
     62     }
     63 
     64     &#64;Override
     65     protected void onHandleIntent(Intent intent) {
     66         MovieDatabase database = MovieDatabase.instance(getApplicationContext());
     67         List<Movie> recommendations = database.recommendations();
     68 
     69         int count = 0;
     70 
     71         try {
     72             for (Movie movie : recommendations) {
     73                 // build the individual content recommendations
     74                 buildRecommendation(getApplicationContext(), movie);
     75 
     76                 if (++count >= MAX_RECOMMENDATIONS) {
     77                     break;
     78                 }
     79             }
     80         } catch (IOException e) {
     81             Log.e(TAG, "Unable to update recommendation", e);
     82         }
     83     }
     84 }
     85 </pre>
     86 
     87 <p>
     88   In order for this service to be recognized by the system and run, register it using your
     89   app manifest. The following code snippet illustrates how to declare this class as a service:
     90 </p>
     91 
     92 <pre>
     93 &lt;manifest ... &gt;
     94   &lt;application ... &gt;
     95     ...
     96 
     97     &lt;service android:name=&quot;.RecommendationsService&quot;
     98              android:enabled=&quot;true&quot; android:exported=&quot;true&quot;/&gt;
     99   &lt;/application&gt;
    100 &lt;/manifest&gt;
    101 </pre>
    102 
    103 
    104 <h2 id="build">Build Recommendations</h2>
    105 
    106 <p>
    107   Once your recommendation server starts running, it must create recommendations and pass them to
    108   the Android framework. The framework receives the recommendations as {@link
    109   android.app.Notification} objects that use a specific template and are marked with a specific
    110   category.
    111 </p>
    112 
    113 <p>
    114   The following code example demonstrates how to get an instance of the {@link
    115   android.app.NotificationManager}, build a recommendation, and post it to the manager:
    116 </p>
    117 
    118 <pre>
    119 public class RecommendationsService extends IntentService {
    120 
    121     ...
    122 
    123     public Notification buildRecommendation(Context context, Movie movie)
    124             throws IOException {
    125 
    126         if (mNotificationManager == null) {
    127             mNotificationManager = (NotificationManager)
    128                     mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    129         }
    130 
    131         Bundle extras = new Bundle();
    132         if (mBackgroundUri != movie.getBackgroundUri()) {
    133             extras.putString(EXTRA_BACKGROUND_IMAGE_URL, movie.getBackgroundUri());
    134         }
    135 
    136         // build the recommendation as a Notification object
    137         Notification notification = new NotificationCompat.BigPictureStyle(
    138                 new NotificationCompat.Builder(context)
    139                         .setContentTitle(movie.getTitle())
    140                         .setContentText(movie.getDescription())
    141                         .setContentInfo(APP_NAME)
    142                         .setGroup("ActionMovies")
    143                         .setSortKey("0.8")
    144                         .setPriority(movie.getPriority())
    145                         .setColor(#FFFF2020)
    146                         .setCategory("recommendation")
    147                         .setLargeIcon(movie.getImage())
    148                         .setSmallIcon(movie.getSmallIcon())
    149                         .setContentIntent(buildPendingIntent(movie.getId()))
    150                         .setExtras(extras))
    151                 .build();
    152 
    153         // post the recommendation to the NotificationManager
    154         mNotificationManager.notify(movie.getId(), notification);
    155         mNotificationManager = null;
    156         return notification;
    157     }
    158 
    159     private PendingIntent buildPendingIntent(long id) {
    160         Intent detailsIntent = new Intent(this, DetailsActivity.class);
    161         detailsIntent.putExtra("id", id);
    162 
    163         TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    164         stackBuilder.addParentStack(DetailsActivity.class);
    165         stackBuilder.addNextIntent(detailsIntent);
    166         // Ensure each PendingIntent is unique
    167         detailsIntent.setAction(Long.toString(id));
    168 
    169         PendingIntent intent = stackBuilder.getPendingIntent(
    170                 0, PendingIntent.FLAG_UPDATE_CURRENT);
    171         return intent;
    172     }
    173 }
    174 </pre>
    175 
    176 
    177 <h3 id="run-service">Run Recommendations Service</h3>
    178 
    179 <p>
    180   Your app's recommendation service must run periodically in order to create current
    181   recommendations. To run your service, create a class that runs a timer and invokes
    182   it at regular intervals. The following code example extends the {@link
    183   android.content.BroadcastReceiver} class to start periodic execution of a recommendation service
    184   every 12 hours:
    185 </p>
    186 
    187 <pre>
    188 public class BootupReceiver extends BroadcastReceiver {
    189     private static final String TAG = "BootupActivity";
    190 
    191     private static final long INITIAL_DELAY = 5000;
    192 
    193     &#64;Override
    194     public void onReceive(Context context, Intent intent) {
    195         if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
    196             scheduleRecommendationUpdate(context);
    197         }
    198     }
    199 
    200     private void scheduleRecommendationUpdate(Context context) {
    201         AlarmManager alarmManager = (AlarmManager)context.getSystemService(
    202                 Context.ALARM_SERVICE);
    203         Intent recommendationIntent = new Intent(context,
    204                 UpdateRecommendationsService.class);
    205         PendingIntent alarmIntent = PendingIntent.getService(context, 0,
    206                 recommendationIntent, 0);
    207 
    208         alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    209                 INITIAL_DELAY,
    210                 AlarmManager.INTERVAL_HALF_DAY,
    211                 alarmIntent);
    212     }
    213 }
    214 </pre>
    215 
    216 <p>
    217   This implementation of the {@link android.content.BroadcastReceiver} class must run after start
    218   up of the TV device where it is installed. To accomplish this, register this class in your app
    219   manifest with an intent filter that listens for the completion of the device boot process. The
    220   following sample code demonstrates how to add this configuration to the manifest:
    221 </p>
    222 
    223 <pre>
    224 &lt;manifest ... &gt;
    225   &lt;application ... &gt;
    226     &lt;receiver android:name=&quot;.BootupReceiver&quot; android:enabled=&quot;true&quot;
    227               android:exported=&quot;false&quot;&gt;
    228       &lt;intent-filter&gt;
    229         &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;/&gt;
    230       &lt;/intent-filter&gt;
    231     &lt;/receiver&gt;
    232   &lt;/application&gt;
    233 &lt;/manifest&gt;
    234 </pre>
    235 
    236 <p class="important">
    237   <strong>Important:</strong> Receiving a boot completed notification requires that your app
    238   requests the {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission.
    239   For more information, see {@link android.content.Intent#ACTION_BOOT_COMPLETED}.
    240 </p>
    241