1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.example.android.tv.channelsprograms.playback; 16 17 import android.content.ContentUris; 18 import android.content.Context; 19 import android.net.Uri; 20 import android.support.annotation.NonNull; 21 import android.support.media.tv.TvContractCompat; 22 import android.support.media.tv.WatchNextProgram; 23 import android.util.Log; 24 25 import com.example.android.tv.channelsprograms.model.MockDatabase; 26 import com.example.android.tv.channelsprograms.model.Movie; 27 import com.example.android.tv.channelsprograms.util.AppLinkHelper; 28 29 /** Adds, updates, and removes the currently playing {@link Movie} from the "Watch Next" channel. */ 30 public class WatchNextAdapter { 31 32 private static final String TAG = "WatchNextAdapter"; 33 updateProgress( Context context, long channelId, Movie movie, long position, long duration)34 public void updateProgress( 35 Context context, long channelId, Movie movie, long position, long duration) { 36 Log.d(TAG, String.format("Updating the movie (%d) in watch next.", movie.getId())); 37 38 Movie entity = MockDatabase.findMovieById(context, channelId, movie.getId()); 39 if (entity == null) { 40 Log.e( 41 TAG, 42 String.format( 43 "Could not find movie in channel: channel id: %d, movie id: %d", 44 channelId, movie.getId())); 45 return; 46 } 47 48 // TODO: step 12 add watch next program. 49 WatchNextProgram program = createWatchNextProgram(channelId, entity, position, duration); 50 if (entity.getWatchNextId() < 1L) { 51 // Create a program. 52 Uri watchNextProgramUri = 53 context.getContentResolver() 54 .insert( 55 TvContractCompat.WatchNextPrograms.CONTENT_URI, 56 program.toContentValues()); 57 long watchNextId = ContentUris.parseId(watchNextProgramUri); 58 entity.setWatchNextId(watchNextId); 59 MockDatabase.saveMovie(context, channelId, entity); 60 61 Log.d(TAG, "Watch Next program added: " + watchNextId); 62 } else { 63 // TODO: step 14 update program. 64 // Updates the progress and last engagement time of the program. 65 context.getContentResolver() 66 .update( 67 TvContractCompat.buildWatchNextProgramUri(entity.getWatchNextId()), 68 program.toContentValues(), 69 null, 70 null); 71 72 Log.d(TAG, "Watch Next program updated: " + entity.getWatchNextId()); 73 } 74 } 75 76 @NonNull createWatchNextProgram( long channelId, Movie movie, long position, long duration)77 private WatchNextProgram createWatchNextProgram( 78 long channelId, Movie movie, long position, long duration) { 79 // TODO: step 13 convert movie 80 Uri posterArtUri = Uri.parse(movie.getCardImageUrl()); 81 Uri intentUri = AppLinkHelper.buildPlaybackUri(channelId, movie.getId(), position); 82 83 WatchNextProgram.Builder builder = new WatchNextProgram.Builder(); 84 builder.setType(TvContractCompat.PreviewProgramColumns.TYPE_MOVIE) 85 .setWatchNextType(TvContractCompat.WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE) 86 .setLastEngagementTimeUtcMillis(System.currentTimeMillis()) 87 .setLastPlaybackPositionMillis((int) position) 88 .setDurationMillis((int) duration) 89 .setTitle(movie.getTitle()) 90 .setDescription(movie.getDescription()) 91 .setPosterArtUri(posterArtUri) 92 .setIntentUri(intentUri); 93 return builder.build(); 94 } 95 removeFromWatchNext(Context context, long channelId, long movieId)96 public void removeFromWatchNext(Context context, long channelId, long movieId) { 97 Movie movie = MockDatabase.findMovieById(context, channelId, movieId); 98 if (movie == null || movie.getWatchNextId() < 1L) { 99 Log.d(TAG, "No program to remove from watch next."); 100 return; 101 } 102 103 // TODO: step 15 remove program 104 int rows = 105 context.getContentResolver() 106 .delete( 107 TvContractCompat.buildWatchNextProgramUri(movie.getWatchNextId()), 108 null, 109 null); 110 Log.d(TAG, String.format("Deleted %d programs(s) from watch next", rows)); 111 112 // Sync our records with the system; remove reference to watch next program. 113 movie.setWatchNextId(-1); 114 MockDatabase.saveMovie(context, channelId, movie); 115 } 116 } 117