1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.tvleanback.recommendation; 18 19 import android.app.IntentService; 20 import android.app.Notification; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.app.TaskStackBuilder; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.graphics.Bitmap; 27 import android.util.Log; 28 29 import com.bumptech.glide.Glide; 30 import com.example.android.tvleanback.R; 31 import com.example.android.tvleanback.data.VideoProvider; 32 import com.example.android.tvleanback.model.Movie; 33 import com.example.android.tvleanback.ui.MovieDetailsActivity; 34 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.HashMap; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.concurrent.ExecutionException; 41 42 /* 43 * This class builds up to MAX_RECOMMMENDATIONS of recommendations and defines what happens 44 * when they're clicked from Recommendations section on Home screen 45 */ 46 public class UpdateRecommendationsService extends IntentService { 47 private static final String TAG = "RecommendationsService"; 48 private static final int MAX_RECOMMENDATIONS = 3; 49 50 private static final int CARD_WIDTH = 313; 51 private static final int CARD_HEIGHT = 176; 52 53 private NotificationManager mNotificationManager; 54 55 public UpdateRecommendationsService() { 56 super(TAG); 57 } 58 59 @Override 60 protected void onHandleIntent(Intent intent) { 61 Log.d(TAG, "Updating recommendation cards"); 62 HashMap<String, List<Movie>> recommendations = VideoProvider.getMovieList(); 63 if (recommendations == null) { 64 return; 65 } 66 67 if (mNotificationManager == null) { 68 mNotificationManager = (NotificationManager) getApplicationContext() 69 .getSystemService(Context.NOTIFICATION_SERVICE); 70 } 71 72 RecommendationBuilder builder = new RecommendationBuilder() 73 .setContext(getApplicationContext()) 74 .setSmallIcon(R.drawable.videos_by_google_icon); 75 76 // flatten to list 77 List flattenedRecommendations = new ArrayList(); 78 for (Map.Entry<String, List<Movie>> entry : recommendations.entrySet()) { 79 for (Movie movie : entry.getValue()) { 80 Log.d(TAG, "Recommendation - " + movie.getTitle()); 81 flattenedRecommendations.add(movie); 82 } 83 } 84 85 Collections.shuffle(flattenedRecommendations); 86 Movie movie; 87 for (int i = 0; i < flattenedRecommendations.size() && i < MAX_RECOMMENDATIONS; i++) { 88 movie = (Movie) flattenedRecommendations.get(i); 89 final RecommendationBuilder notificationBuilder = builder 90 .setBackground(movie.getCardImageUrl()) 91 .setId(i+1) 92 .setPriority(MAX_RECOMMENDATIONS - i - 1) 93 .setTitle(movie.getTitle()) 94 .setDescription(getString(R.string.popular_header)) 95 .setIntent(buildPendingIntent(movie, i + 1)); 96 97 try { 98 Bitmap bitmap = Glide.with(getApplicationContext()) 99 .load(movie.getCardImageUrl()) 100 .asBitmap() 101 .into(CARD_WIDTH, CARD_HEIGHT) // Only use for synchronous .get() 102 .get(); 103 notificationBuilder.setBitmap(bitmap); 104 Notification notification = notificationBuilder.build(); 105 mNotificationManager.notify(i + 1, notification); 106 } catch (InterruptedException | ExecutionException e) { 107 Log.e(TAG, "Could not create recommendation: " + e); 108 } 109 } 110 } 111 112 private PendingIntent buildPendingIntent(Movie movie, int id) { 113 Intent detailsIntent = new Intent(this, MovieDetailsActivity.class); 114 detailsIntent.putExtra(MovieDetailsActivity.MOVIE, movie); 115 detailsIntent.putExtra(MovieDetailsActivity.NOTIFICATION_ID, id); 116 117 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 118 stackBuilder.addParentStack(MovieDetailsActivity.class); 119 stackBuilder.addNextIntent(detailsIntent); 120 // Ensure a unique PendingIntents, otherwise all recommendations end up with the same 121 // PendingIntent 122 detailsIntent.setAction(movie.getId()); 123 124 return stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 125 } 126 } 127