1/* 2 * Copyright (C) 2017 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 */ 16package android.support.media.tv; 17 18import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 19 20import android.annotation.TargetApi; 21import android.content.ContentValues; 22import android.database.Cursor; 23import android.os.Build; 24import android.support.annotation.RestrictTo; 25import android.support.media.tv.TvContractCompat.PreviewPrograms; 26 27/** 28 * A convenience class to access {@link PreviewPrograms} entries in the system content 29 * provider. 30 * 31 * <p>This class makes it easy to insert or retrieve a preview program from the system content 32 * provider, which is defined in {@link TvContractCompat}. 33 * 34 * <p>Usage example when inserting a preview program: 35 * <pre> 36 * PreviewProgram previewProgram = new PreviewProgram.Builder() 37 * .setChannelId(channel.getId()) 38 * .setType(PreviewPrograms.TYPE_MOVIE) 39 * .setTitle("Program Title") 40 * .setDescription("Program Description") 41 * .setPosterArtUri(Uri.parse("http://example.com/poster_art.png")) 42 * // Set more attributes... 43 * .build(); 44 * Uri previewProgramUri = getContentResolver().insert(PreviewPrograms.CONTENT_URI, 45 * previewProgram.toContentValues()); 46 * </pre> 47 * 48 * <p>Usage example when retrieving a preview program: 49 * <pre> 50 * PreviewProgram previewProgram; 51 * try (Cursor cursor = resolver.query(previewProgramUri, null, null, null, null)) { 52 * if (cursor != null && cursor.getCount() != 0) { 53 * cursor.moveToNext(); 54 * previewProgram = PreviewProgram.fromCursor(cursor); 55 * } 56 * } 57 * </pre> 58 * 59 * <p>Usage example when updating an existing preview program: 60 * <pre> 61 * PreviewProgram updatedProgram = new PreviewProgram.Builder(previewProgram) 62 * .setWeight(20) 63 * .build(); 64 * getContentResolver().update(TvContractCompat.buildPreviewProgramUri(updatedProgram.getId()), 65 * updatedProgram.toContentValues(), null, null); 66 * </pre> 67 * 68 * <p>Usage example when deleting a preview program: 69 * <pre> 70 * getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(existingProgram.getId()), 71 * null, null); 72 * </pre> 73 */ 74@TargetApi(26) 75public final class PreviewProgram extends BasePreviewProgram { 76 /** 77 * @hide 78 */ 79 @RestrictTo(LIBRARY_GROUP) 80 public static final String[] PROJECTION = getProjection(); 81 82 private static final long INVALID_LONG_VALUE = -1; 83 private static final int INVALID_INT_VALUE = -1; 84 85 private PreviewProgram(Builder builder) { 86 super(builder); 87 } 88 89 /** 90 * @return The value of {@link PreviewPrograms#COLUMN_CHANNEL_ID} for the program. 91 */ 92 public long getChannelId() { 93 Long l = mValues.getAsLong(PreviewPrograms.COLUMN_CHANNEL_ID); 94 return l == null ? INVALID_LONG_VALUE : l; 95 } 96 97 /** 98 * @return The value of {@link PreviewPrograms#COLUMN_WEIGHT} for the program. 99 */ 100 public int getWeight() { 101 Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_WEIGHT); 102 return i == null ? INVALID_INT_VALUE : i; 103 } 104 105 @Override 106 public boolean equals(Object other) { 107 if (!(other instanceof PreviewProgram)) { 108 return false; 109 } 110 return mValues.equals(((PreviewProgram) other).mValues); 111 } 112 113 @Override 114 public String toString() { 115 return "PreviewProgram{" + mValues.toString() + "}"; 116 } 117 118 /** 119 * @return The fields of the Program in the ContentValues format to be easily inserted into the 120 * TV Input Framework database. 121 */ 122 @Override 123 public ContentValues toContentValues() { 124 return toContentValues(false); 125 } 126 127 /** 128 * Returns fields of the PreviewProgram in the ContentValues format to be easily inserted 129 * into the TV Input Framework database. 130 * 131 * @param includeProtectedFields Whether the fields protected by system is included or not. 132 * @hide 133 */ 134 @RestrictTo(LIBRARY_GROUP) 135 @Override 136 public ContentValues toContentValues(boolean includeProtectedFields) { 137 ContentValues values = super.toContentValues(includeProtectedFields); 138 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { 139 values.remove(PreviewPrograms.COLUMN_CHANNEL_ID); 140 values.remove(PreviewPrograms.COLUMN_WEIGHT); 141 } 142 return values; 143 } 144 145 /** 146 * Creates a Program object from a cursor including the fields defined in 147 * {@link PreviewPrograms}. 148 * 149 * @param cursor A row from the TV Input Framework database. 150 * @return A Program with the values taken from the cursor. 151 */ 152 public static PreviewProgram fromCursor(Cursor cursor) { 153 // TODO: Add additional API which does not use costly getColumnIndex(). 154 Builder builder = new Builder(); 155 BasePreviewProgram.setFieldsFromCursor(cursor, builder); 156 int index; 157 if ((index = cursor.getColumnIndex(PreviewPrograms.COLUMN_CHANNEL_ID)) >= 0 158 && !cursor.isNull(index)) { 159 builder.setChannelId(cursor.getLong(index)); 160 } 161 if ((index = cursor.getColumnIndex(PreviewPrograms.COLUMN_WEIGHT)) >= 0 162 && !cursor.isNull(index)) { 163 builder.setWeight(cursor.getInt(index)); 164 } 165 return builder.build(); 166 } 167 168 private static String[] getProjection() { 169 String[] oColumns = new String[] { 170 PreviewPrograms.COLUMN_CHANNEL_ID, 171 PreviewPrograms.COLUMN_WEIGHT, 172 }; 173 return CollectionUtils.concatAll(BasePreviewProgram.PROJECTION, oColumns); 174 } 175 176 /** 177 * This Builder class simplifies the creation of a {@link PreviewProgram} object. 178 */ 179 public static final class Builder extends BasePreviewProgram.Builder<Builder> { 180 181 /** 182 * Creates a new Builder object. 183 */ 184 public Builder() { 185 } 186 187 /** 188 * Creates a new Builder object with values copied from another Program. 189 * @param other The Program you're copying from. 190 */ 191 public Builder(PreviewProgram other) { 192 mValues = new ContentValues(other.mValues); 193 } 194 195 /** 196 * Sets the ID of the {@link Channel} that contains this program. 197 * 198 * @param channelId The value of {@link PreviewPrograms#COLUMN_CHANNEL_ID for the program. 199 * @return This Builder object to allow for chaining of calls to builder methods. 200 */ 201 public Builder setChannelId(long channelId) { 202 mValues.put(PreviewPrograms.COLUMN_CHANNEL_ID, channelId); 203 return this; 204 } 205 206 /** 207 * Sets the weight of the preview program within the channel. 208 * 209 * @param weight The value of {@link PreviewPrograms#COLUMN_WEIGHT} for the program. 210 * @return This Builder object to allow for chaining of calls to builder methods. 211 */ 212 public Builder setWeight(int weight) { 213 mValues.put(PreviewPrograms.COLUMN_WEIGHT, weight); 214 return this; 215 } 216 217 /** 218 * @return A new Program with values supplied by the Builder. 219 */ 220 public PreviewProgram build() { 221 return new PreviewProgram(this); 222 } 223 } 224} 225