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.content.ContentValues; 21import android.database.Cursor; 22import android.media.tv.TvContentRating; 23import android.net.Uri; 24import android.os.Build; 25import android.support.annotation.RestrictTo; 26import android.support.media.tv.TvContractCompat.BaseTvColumns; 27import android.support.media.tv.TvContractCompat.ProgramColumns; 28import android.support.media.tv.TvContractCompat.ProgramColumns.ReviewRatingStyle; 29import android.support.media.tv.TvContractCompat.Programs; 30import android.support.media.tv.TvContractCompat.Programs.Genres.Genre; 31 32/** 33 * Base class for derived classes that want to have common fields for programs defined in 34 * {@link TvContractCompat}. 35 */ 36public abstract class BaseProgram { 37 /** 38 * @hide 39 */ 40 @RestrictTo(LIBRARY_GROUP) 41 public static final String[] PROJECTION = getProjection(); 42 43 private static final long INVALID_LONG_VALUE = -1; 44 private static final int INVALID_INT_VALUE = -1; 45 private static final int IS_SEARCHABLE = 1; 46 47 /** @hide */ 48 @RestrictTo(LIBRARY_GROUP) 49 protected ContentValues mValues; 50 51 /* package-private */ 52 BaseProgram(Builder builder) { 53 mValues = builder.mValues; 54 } 55 56 /** 57 * @return The ID for the program. 58 * @see BaseTvColumns#_ID 59 */ 60 public long getId() { 61 Long l = mValues.getAsLong(BaseTvColumns._ID); 62 return l == null ? INVALID_LONG_VALUE : l; 63 } 64 65 /** 66 * @return The package name for the program. 67 * @see BaseTvColumns#COLUMN_PACKAGE_NAME 68 * @hide 69 */ 70 @RestrictTo(LIBRARY_GROUP) 71 public String getPackageName() { 72 return mValues.getAsString(BaseTvColumns.COLUMN_PACKAGE_NAME); 73 } 74 75 /** 76 * @return The title for the program. 77 * @see Programs#COLUMN_TITLE 78 */ 79 public String getTitle() { 80 return mValues.getAsString(Programs.COLUMN_TITLE); 81 } 82 83 /** 84 * @return The episode title for the program. 85 * @see Programs#COLUMN_EPISODE_TITLE 86 */ 87 public String getEpisodeTitle() { 88 return mValues.getAsString(Programs.COLUMN_EPISODE_TITLE); 89 } 90 91 /** 92 * @return The season display number for the program. 93 * @see Programs#COLUMN_SEASON_DISPLAY_NUMBER 94 */ 95 public String getSeasonNumber() { 96 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 97 return mValues.getAsString(Programs.COLUMN_SEASON_DISPLAY_NUMBER); 98 } else { 99 return mValues.getAsString(Programs.COLUMN_SEASON_NUMBER); 100 } 101 } 102 103 /** 104 * @return The episode display number for the program. 105 * @see Programs#COLUMN_EPISODE_DISPLAY_NUMBER 106 */ 107 public String getEpisodeNumber() { 108 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 109 return mValues.getAsString(Programs.COLUMN_EPISODE_DISPLAY_NUMBER); 110 } else { 111 return mValues.getAsString(Programs.COLUMN_EPISODE_NUMBER); 112 } 113 } 114 115 /** 116 * @return The short description for the program. 117 * @see Programs#COLUMN_SHORT_DESCRIPTION 118 */ 119 public String getDescription() { 120 return mValues.getAsString(Programs.COLUMN_SHORT_DESCRIPTION); 121 } 122 123 /** 124 * @return The long description for the program. 125 * @see Programs#COLUMN_LONG_DESCRIPTION 126 */ 127 public String getLongDescription() { 128 return mValues.getAsString(Programs.COLUMN_LONG_DESCRIPTION); 129 } 130 131 /** 132 * @return The video width for the program. 133 * @see Programs#COLUMN_VIDEO_WIDTH 134 */ 135 public int getVideoWidth() { 136 Integer i = mValues.getAsInteger(Programs.COLUMN_VIDEO_WIDTH); 137 return i == null ? INVALID_INT_VALUE : i; 138 } 139 140 /** 141 * @return The video height for the program. 142 * @see Programs#COLUMN_VIDEO_HEIGHT 143 */ 144 public int getVideoHeight() { 145 Integer i = mValues.getAsInteger(Programs.COLUMN_VIDEO_HEIGHT); 146 return i == null ? INVALID_INT_VALUE : i; 147 } 148 149 /** 150 * @return The canonical genre for the program. 151 * @see Programs#COLUMN_CANONICAL_GENRE 152 */ 153 public @Genre String[] getCanonicalGenres() { 154 return Programs.Genres.decode(mValues.getAsString(Programs.COLUMN_CANONICAL_GENRE)); 155 } 156 157 /** 158 * @return The content rating for the program. 159 * @see Programs#COLUMN_CONTENT_RATING 160 */ 161 public TvContentRating[] getContentRatings() { 162 return TvContractUtils.stringToContentRatings(mValues.getAsString( 163 Programs.COLUMN_CONTENT_RATING)); 164 } 165 166 /** 167 * @return The poster art URI for the program. 168 * @see Programs#COLUMN_POSTER_ART_URI 169 */ 170 public Uri getPosterArtUri() { 171 String uri = mValues.getAsString(Programs.COLUMN_POSTER_ART_URI); 172 return uri == null ? null : Uri.parse(uri); 173 } 174 175 /** 176 * @return The thumbnail URI for the program. 177 * @see Programs#COLUMN_THUMBNAIL_URI 178 */ 179 public Uri getThumbnailUri() { 180 String uri = mValues.getAsString(Programs.COLUMN_POSTER_ART_URI); 181 return uri == null ? null : Uri.parse(uri); 182 } 183 184 /** 185 * @return The internal provider data for the program. 186 * @see Programs#COLUMN_INTERNAL_PROVIDER_DATA 187 */ 188 public byte[] getInternalProviderDataByteArray() { 189 return mValues.getAsByteArray(Programs.COLUMN_INTERNAL_PROVIDER_DATA); 190 } 191 192 /** 193 * @return The audio languages for the program. 194 * @see Programs#COLUMN_AUDIO_LANGUAGE 195 */ 196 public String[] getAudioLanguages() { 197 return TvContractUtils.stringToAudioLanguages(mValues.getAsString( 198 Programs.COLUMN_AUDIO_LANGUAGE)); 199 } 200 201 /** 202 * @return Whether the program is searchable or not. 203 * @see Programs#COLUMN_SEARCHABLE 204 */ 205 public boolean isSearchable() { 206 Integer i = mValues.getAsInteger(Programs.COLUMN_SEARCHABLE); 207 return i == null || i == IS_SEARCHABLE; 208 } 209 210 /** 211 * @return The first internal provider flag for the program. 212 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG1 213 */ 214 public Long getInternalProviderFlag1() { 215 return mValues.getAsLong(Programs.COLUMN_INTERNAL_PROVIDER_FLAG1); 216 } 217 218 /** 219 * @return The second internal provider flag for the program. 220 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG2 221 */ 222 public Long getInternalProviderFlag2() { 223 return mValues.getAsLong(Programs.COLUMN_INTERNAL_PROVIDER_FLAG2); 224 } 225 226 /** 227 * @return The third internal provider flag for the program. 228 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG3 229 */ 230 public Long getInternalProviderFlag3() { 231 return mValues.getAsLong(Programs.COLUMN_INTERNAL_PROVIDER_FLAG3); 232 } 233 234 /** 235 * @return The forth internal provider flag for the program. 236 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG4 237 */ 238 public Long getInternalProviderFlag4() { 239 return mValues.getAsLong(Programs.COLUMN_INTERNAL_PROVIDER_FLAG4); 240 } 241 242 /** 243 * @return The season title for the program. 244 * @see Programs#COLUMN_SEASON_TITLE 245 */ 246 public String getSeasonTitle() { 247 return mValues.getAsString(Programs.COLUMN_SEASON_TITLE); 248 } 249 250 /** 251 * @return The review rating style for the program. 252 * @see Programs#COLUMN_REVIEW_RATING_STYLE 253 */ 254 public @ReviewRatingStyle int getReviewRatingStyle() { 255 Integer i = mValues.getAsInteger(Programs.COLUMN_REVIEW_RATING_STYLE); 256 return i == null ? INVALID_INT_VALUE : i; 257 } 258 259 /** 260 * @return The review rating for the program. 261 * @see Programs#COLUMN_REVIEW_RATING 262 */ 263 public String getReviewRating() { 264 return mValues.getAsString(Programs.COLUMN_REVIEW_RATING); 265 } 266 267 @Override 268 public int hashCode() { 269 return mValues.hashCode(); 270 } 271 272 @Override 273 public boolean equals(Object other) { 274 if (!(other instanceof BaseProgram)) { 275 return false; 276 } 277 return mValues.equals(((BaseProgram) other).mValues); 278 } 279 280 @Override 281 public String toString() { 282 return "BaseProgram{" + mValues.toString() + "}"; 283 } 284 285 /** 286 * @return The fields of the BaseProgram in {@link ContentValues} format to be easily inserted 287 * into the TV Input Framework database. 288 */ 289 public ContentValues toContentValues() { 290 ContentValues values = new ContentValues(mValues); 291 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 292 values.remove(ProgramColumns.COLUMN_SEARCHABLE); 293 values.remove(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG1); 294 values.remove(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG2); 295 values.remove(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG3); 296 values.remove(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG4); 297 } 298 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { 299 values.remove(ProgramColumns.COLUMN_SEASON_TITLE); 300 } 301 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { 302 values.remove(ProgramColumns.COLUMN_REVIEW_RATING_STYLE); 303 values.remove(ProgramColumns.COLUMN_REVIEW_RATING); 304 } 305 return values; 306 } 307 308 /** 309 * Sets the fields in the cursor to the given builder instance. 310 * 311 * @param cursor A row from the TV Input Framework database. 312 * @param builder A Builder to set the fields. 313 */ 314 static void setFieldsFromCursor(Cursor cursor, Builder builder) { 315 // TODO: Add additional API which does not use costly getColumnIndex(). 316 int index; 317 if ((index = cursor.getColumnIndex(BaseTvColumns._ID)) >= 0 && !cursor.isNull(index)) { 318 builder.setId(cursor.getLong(index)); 319 } 320 if ((index = cursor.getColumnIndex(BaseTvColumns.COLUMN_PACKAGE_NAME)) >= 0 321 && !cursor.isNull(index)) { 322 builder.setPackageName(cursor.getString(index)); 323 } 324 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_TITLE)) >= 0 325 && !cursor.isNull(index)) { 326 builder.setTitle(cursor.getString(index)); 327 } 328 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_EPISODE_TITLE)) >= 0 329 && !cursor.isNull(index)) { 330 builder.setEpisodeTitle(cursor.getString(index)); 331 } 332 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 333 if ((index = 334 cursor.getColumnIndex(ProgramColumns.COLUMN_SEASON_DISPLAY_NUMBER)) >= 0 335 && !cursor.isNull(index)) { 336 builder.setSeasonNumber(cursor.getString(index), INVALID_INT_VALUE); 337 } 338 } else { 339 if ((index = cursor.getColumnIndex(Programs.COLUMN_SEASON_NUMBER)) >= 0 340 && !cursor.isNull(index)) { 341 builder.setSeasonNumber(cursor.getInt(index)); 342 } 343 } 344 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 345 if ((index = 346 cursor.getColumnIndex(ProgramColumns.COLUMN_EPISODE_DISPLAY_NUMBER)) >= 0 347 && !cursor.isNull(index)) { 348 builder.setEpisodeNumber(cursor.getString(index), INVALID_INT_VALUE); 349 } 350 } else { 351 if ((index = cursor.getColumnIndex(Programs.COLUMN_EPISODE_NUMBER)) >= 0 352 && !cursor.isNull(index)) { 353 builder.setEpisodeNumber(cursor.getInt(index)); 354 } 355 } 356 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_SHORT_DESCRIPTION)) >= 0 357 && !cursor.isNull(index)) { 358 builder.setDescription(cursor.getString(index)); 359 } 360 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_LONG_DESCRIPTION)) >= 0 361 && !cursor.isNull(index)) { 362 builder.setLongDescription(cursor.getString(index)); 363 } 364 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_POSTER_ART_URI)) >= 0 365 && !cursor.isNull(index)) { 366 builder.setPosterArtUri(Uri.parse(cursor.getString(index))); 367 } 368 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_THUMBNAIL_URI)) >= 0 369 && !cursor.isNull(index)) { 370 builder.setThumbnailUri(Uri.parse(cursor.getString(index))); 371 } 372 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_AUDIO_LANGUAGE)) >= 0 373 && !cursor.isNull(index)) { 374 builder.setAudioLanguages( 375 TvContractUtils.stringToAudioLanguages(cursor.getString(index))); 376 } 377 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_CANONICAL_GENRE)) >= 0 378 && !cursor.isNull(index)) { 379 builder.setCanonicalGenres(Programs.Genres.decode( 380 cursor.getString(index))); 381 } 382 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_CONTENT_RATING)) >= 0 383 && !cursor.isNull(index)) { 384 builder.setContentRatings( 385 TvContractUtils.stringToContentRatings(cursor.getString(index))); 386 } 387 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_VIDEO_WIDTH)) >= 0 388 && !cursor.isNull(index)) { 389 builder.setVideoWidth((int) cursor.getLong(index)); 390 } 391 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_VIDEO_HEIGHT)) >= 0 392 && !cursor.isNull(index)) { 393 builder.setVideoHeight((int) cursor.getLong(index)); 394 } 395 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_INTERNAL_PROVIDER_DATA)) >= 0 396 && !cursor.isNull(index)) { 397 builder.setInternalProviderData(cursor.getBlob(index)); 398 } 399 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 400 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_SEARCHABLE)) >= 0 401 && !cursor.isNull(index)) { 402 builder.setSearchable(cursor.getInt(index) == IS_SEARCHABLE); 403 } 404 if ((index = 405 cursor.getColumnIndex(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG1)) >= 0 406 && !cursor.isNull(index)) { 407 builder.setInternalProviderFlag1(cursor.getLong(index)); 408 } 409 if ((index = 410 cursor.getColumnIndex(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG2)) >= 0 411 && !cursor.isNull(index)) { 412 builder.setInternalProviderFlag2(cursor.getLong(index)); 413 } 414 if ((index = 415 cursor.getColumnIndex(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG3)) >= 0 416 && !cursor.isNull(index)) { 417 builder.setInternalProviderFlag3(cursor.getLong(index)); 418 } 419 if ((index = 420 cursor.getColumnIndex(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG4)) >= 0 421 && !cursor.isNull(index)) { 422 builder.setInternalProviderFlag4(cursor.getLong(index)); 423 } 424 } 425 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 426 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_SEASON_TITLE)) >= 0 427 && !cursor.isNull(index)) { 428 builder.setSeasonTitle(cursor.getString(index)); 429 } 430 } 431 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 432 if ((index = cursor.getColumnIndex( 433 ProgramColumns.COLUMN_REVIEW_RATING_STYLE)) >= 0 434 && !cursor.isNull(index)) { 435 builder.setReviewRatingStyle(cursor.getInt(index)); 436 } 437 if ((index = cursor.getColumnIndex(ProgramColumns.COLUMN_REVIEW_RATING)) >= 0 438 && !cursor.isNull(index)) { 439 builder.setReviewRating(cursor.getString(index)); 440 } 441 } 442 } 443 444 private static String[] getProjection() { 445 String[] baseColumns = new String[] { 446 BaseTvColumns._ID, 447 BaseTvColumns.COLUMN_PACKAGE_NAME, 448 ProgramColumns.COLUMN_TITLE, 449 ProgramColumns.COLUMN_EPISODE_TITLE, 450 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) 451 ? ProgramColumns.COLUMN_SEASON_DISPLAY_NUMBER 452 : Programs.COLUMN_SEASON_NUMBER, 453 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) 454 ? ProgramColumns.COLUMN_EPISODE_DISPLAY_NUMBER 455 : Programs.COLUMN_EPISODE_NUMBER, 456 ProgramColumns.COLUMN_SHORT_DESCRIPTION, 457 ProgramColumns.COLUMN_LONG_DESCRIPTION, 458 ProgramColumns.COLUMN_POSTER_ART_URI, 459 ProgramColumns.COLUMN_THUMBNAIL_URI, 460 ProgramColumns.COLUMN_AUDIO_LANGUAGE, 461 ProgramColumns.COLUMN_CANONICAL_GENRE, 462 ProgramColumns.COLUMN_CONTENT_RATING, 463 ProgramColumns.COLUMN_VIDEO_WIDTH, 464 ProgramColumns.COLUMN_VIDEO_HEIGHT, 465 ProgramColumns.COLUMN_INTERNAL_PROVIDER_DATA 466 }; 467 String[] marshmallowColumns = new String[] { 468 ProgramColumns.COLUMN_SEARCHABLE, 469 ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG1, 470 ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG2, 471 ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG3, 472 ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG4, 473 }; 474 String[] nougatColumns = new String[] { 475 ProgramColumns.COLUMN_SEASON_TITLE, 476 }; 477 String[] oColumns = new String[] { 478 ProgramColumns.COLUMN_REVIEW_RATING, 479 ProgramColumns.COLUMN_REVIEW_RATING_STYLE, 480 }; 481 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 482 return CollectionUtils.concatAll(baseColumns, marshmallowColumns, nougatColumns, 483 oColumns); 484 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 485 return CollectionUtils.concatAll(baseColumns, marshmallowColumns, nougatColumns); 486 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 487 return CollectionUtils.concatAll(baseColumns, marshmallowColumns); 488 } else { 489 return baseColumns; 490 } 491 } 492 493 /** 494 * This Builder class simplifies the creation of a {@link BaseProgram} object. 495 * 496 * @param <T> The Builder of the derived classe. 497 */ 498 public abstract static class Builder<T extends Builder> { 499 /** @hide */ 500 @RestrictTo(LIBRARY_GROUP) 501 protected ContentValues mValues; 502 503 /** 504 * Creates a new Builder object. 505 */ 506 public Builder() { 507 mValues = new ContentValues(); 508 } 509 510 /** 511 * Creates a new Builder object with values copied from another Program. 512 * @param other The Program you're copying from. 513 */ 514 public Builder(BaseProgram other) { 515 mValues = new ContentValues(other.mValues); 516 } 517 518 /** 519 * Sets a unique id for this program. 520 * 521 * @param programId The ID for the program. 522 * @return This Builder object to allow for chaining of calls to builder methods. 523 * @see BaseTvColumns#_ID 524 */ 525 public T setId(long programId) { 526 mValues.put(BaseTvColumns._ID, programId); 527 return (T) this; 528 } 529 530 /** 531 * Sets the package name for this program. 532 * 533 * @param packageName The package name for the program. 534 * @return This Builder object to allow for chaining of calls to builder methods. 535 * @see BaseTvColumns#COLUMN_PACKAGE_NAME 536 * @hide 537 */ 538 @RestrictTo(LIBRARY_GROUP) 539 public T setPackageName(String packageName) { 540 mValues.put(BaseTvColumns.COLUMN_PACKAGE_NAME, packageName); 541 return (T) this; 542 } 543 544 /** 545 * Sets the title of this program. For a series, this is the series title. 546 * 547 * @param title The title for the program. 548 * @return This Builder object to allow for chaining of calls to builder methods. 549 * @see Programs#COLUMN_TITLE 550 */ 551 public T setTitle(String title) { 552 mValues.put(Programs.COLUMN_TITLE, title); 553 return (T) this; 554 } 555 556 /** 557 * Sets the title of this particular episode for a series. 558 * 559 * @param episodeTitle The episode title for the program. 560 * @return This Builder object to allow for chaining of calls to builder methods. 561 * @see Programs#COLUMN_EPISODE_TITLE 562 */ 563 public T setEpisodeTitle(String episodeTitle) { 564 mValues.put(Programs.COLUMN_EPISODE_TITLE, episodeTitle); 565 return (T) this; 566 } 567 568 /** 569 * Sets the season number for this episode for a series. 570 * 571 * @param seasonNumber The season display number for the program. 572 * @return This Builder object to allow for chaining of calls to builder methods. 573 * @see Programs#COLUMN_SEASON_DISPLAY_NUMBER 574 */ 575 public T setSeasonNumber(int seasonNumber) { 576 setSeasonNumber(String.valueOf(seasonNumber), seasonNumber); 577 return (T) this; 578 } 579 580 /** 581 * Sets the season number for this episode for a series. 582 * 583 * @param seasonNumber The season display number for the program. 584 * @param numericalSeasonNumber An integer value for {@link Programs#COLUMN_SEASON_NUMBER} 585 * which will be used for API Level 23 and below. 586 * @return This Builder object to allow for chaining of calls to builder methods. 587 * @see Programs#COLUMN_SEASON_DISPLAY_NUMBER 588 * @see Programs#COLUMN_SEASON_NUMBER 589 */ 590 public T setSeasonNumber(String seasonNumber, int numericalSeasonNumber) { 591 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 592 mValues.put(Programs.COLUMN_SEASON_DISPLAY_NUMBER, seasonNumber); 593 } else { 594 mValues.put(Programs.COLUMN_SEASON_NUMBER, numericalSeasonNumber); 595 } 596 return (T) this; 597 } 598 599 /** 600 * Sets the episode number in a season for this episode for a series. 601 * 602 * @param episodeNumber The value of episode display number for the program. 603 * @return This Builder object to allow for chaining of calls to builder methods. 604 * @see Programs#COLUMN_EPISODE_DISPLAY_NUMBER 605 */ 606 public T setEpisodeNumber(int episodeNumber) { 607 setEpisodeNumber(String.valueOf(episodeNumber), episodeNumber); 608 return (T) this; 609 } 610 611 /** 612 * Sets the episode number in a season for this episode for a series. 613 * 614 * @param episodeNumber The value of episode display number for the program. 615 * @param numericalEpisodeNumber An integer value for {@link Programs#COLUMN_EPISODE_NUMBER} 616 * which will be used for API Level 23 and below. 617 * @return This Builder object to allow for chaining of calls to builder methods. 618 * @see Programs#COLUMN_EPISODE_DISPLAY_NUMBER 619 * @see Programs#COLUMN_EPISODE_NUMBER 620 */ 621 public T setEpisodeNumber(String episodeNumber, int numericalEpisodeNumber) { 622 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 623 mValues.put(Programs.COLUMN_EPISODE_DISPLAY_NUMBER, episodeNumber); 624 } else { 625 mValues.put(Programs.COLUMN_EPISODE_NUMBER, numericalEpisodeNumber); 626 } 627 return (T) this; 628 } 629 630 /** 631 * Sets a brief description of the program. For a series, this would be a brief description 632 * of the episode. 633 * 634 * @param description The short description for the program. 635 * @return This Builder object to allow for chaining of calls to builder methods. 636 * @see Programs#COLUMN_SHORT_DESCRIPTION 637 */ 638 public T setDescription(String description) { 639 mValues.put(Programs.COLUMN_SHORT_DESCRIPTION, description); 640 return (T) this; 641 } 642 643 /** 644 * Sets a longer description of a program if one exists. 645 * 646 * @param longDescription The long description for the program. 647 * @return This Builder object to allow for chaining of calls to builder methods. 648 * @see Programs#COLUMN_LONG_DESCRIPTION 649 */ 650 public T setLongDescription(String longDescription) { 651 mValues.put(Programs.COLUMN_LONG_DESCRIPTION, longDescription); 652 return (T) this; 653 } 654 655 /** 656 * Sets the video width of the program. 657 * 658 * @param width The video width for the program. 659 * @return This Builder object to allow for chaining of calls to builder methods. 660 * @see Programs#COLUMN_VIDEO_WIDTH 661 */ 662 public T setVideoWidth(int width) { 663 mValues.put(Programs.COLUMN_VIDEO_WIDTH, width); 664 return (T) this; 665 } 666 667 /** 668 * Sets the video height of the program. 669 * 670 * @param height The video height for the program. 671 * @return This Builder object to allow for chaining of calls to builder methods. 672 * @see Programs#COLUMN_VIDEO_HEIGHT 673 */ 674 public T setVideoHeight(int height) { 675 mValues.put(Programs.COLUMN_VIDEO_HEIGHT, height); 676 return (T) this; 677 } 678 679 /** 680 * Sets the content ratings for this program. 681 * 682 * @param contentRatings An array of {@link TvContentRating} that apply to this program 683 * which will be flattened to a String to store in a database. 684 * @return This Builder object to allow for chaining of calls to builder methods. 685 * @see Programs#COLUMN_CONTENT_RATING 686 */ 687 public T setContentRatings(TvContentRating[] contentRatings) { 688 mValues.put(Programs.COLUMN_CONTENT_RATING, 689 TvContractUtils.contentRatingsToString(contentRatings)); 690 return (T) this; 691 } 692 693 /** 694 * Sets the large poster art of the program. 695 * 696 * @param posterArtUri The poster art URI for the program. 697 * @return This Builder object to allow for chaining of calls to builder methods. 698 * @see Programs#COLUMN_POSTER_ART_URI 699 */ 700 public T setPosterArtUri(Uri posterArtUri) { 701 mValues.put(Programs.COLUMN_POSTER_ART_URI, 702 posterArtUri == null ? null : posterArtUri.toString()); 703 return (T) this; 704 } 705 706 /** 707 * Sets a small thumbnail of the program. 708 * 709 * @param thumbnailUri The thumbnail URI for the program. 710 * @return This Builder object to allow for chaining of calls to builder methods. 711 * @see Programs#COLUMN_THUMBNAIL_URI 712 */ 713 public T setThumbnailUri(Uri thumbnailUri) { 714 mValues.put(Programs.COLUMN_THUMBNAIL_URI, 715 thumbnailUri == null ? null : thumbnailUri.toString()); 716 return (T) this; 717 } 718 719 /** 720 * Sets the genres of the program. 721 * 722 * @param genres An array of {@link Programs.Genres} that apply to the program which will be 723 * flattened to a String to store in a database. 724 * @return This Builder object to allow for chaining of calls to builder methods. 725 * @see Programs#COLUMN_CANONICAL_GENRE 726 */ 727 public T setCanonicalGenres(@Genre String[] genres) { 728 mValues.put(Programs.COLUMN_CANONICAL_GENRE, Programs.Genres.encode(genres)); 729 return (T) this; 730 } 731 732 /** 733 * Sets the internal provider data for the program as raw bytes. 734 * 735 * @param data The internal provider data for the program. 736 * @return This Builder object to allow for chaining of calls to builder methods. 737 * @see Programs#COLUMN_INTERNAL_PROVIDER_DATA 738 */ 739 public T setInternalProviderData(byte[] data) { 740 mValues.put(ProgramColumns.COLUMN_INTERNAL_PROVIDER_DATA, data); 741 return (T) this; 742 } 743 744 /** 745 * Sets the available audio languages for this program as an array of strings. 746 * 747 * @param audioLanguages An array of audio languages, in ISO 639-1 or 639-2/T codes, that 748 * apply to this program which will be stored in a database. 749 * @return This Builder object to allow for chaining of calls to builder methods. 750 */ 751 public T setAudioLanguages(String[] audioLanguages) { 752 mValues.put(ProgramColumns.COLUMN_AUDIO_LANGUAGE, 753 TvContractUtils.audioLanguagesToString(audioLanguages)); 754 return (T) this; 755 } 756 757 /** 758 * Sets whether this channel can be searched for in other applications. 759 * 760 * @param searchable Whether the program is searchable or not. 761 * @return This Builder object to allow for chaining of calls to builder methods. 762 * @see Programs#COLUMN_SEARCHABLE 763 */ 764 public T setSearchable(boolean searchable) { 765 mValues.put(Programs.COLUMN_SEARCHABLE, searchable ? IS_SEARCHABLE : 0); 766 return (T) this; 767 } 768 769 /** 770 * Sets the internal provider flag1 for the program. 771 * 772 * @param flag The first internal provider flag for the program. 773 * @return This Builder object to allow for chaining of calls to builder methods. 774 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG1 775 */ 776 public T setInternalProviderFlag1(long flag) { 777 mValues.put(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG1, flag); 778 return (T) this; 779 } 780 781 /** 782 * Sets the internal provider flag2 for the program. 783 * 784 * @param flag The second internal provider flag for the program. 785 * @return This Builder object to allow for chaining of calls to builder methods. 786 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG2 787 */ 788 public T setInternalProviderFlag2(long flag) { 789 mValues.put(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG2, flag); 790 return (T) this; 791 } 792 793 /** 794 * Sets the internal provider flag3 for the program. 795 * 796 * @param flag The third internal provider flag for the program. 797 * @return This Builder object to allow for chaining of calls to builder methods. 798 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG3 799 */ 800 public T setInternalProviderFlag3(long flag) { 801 mValues.put(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG3, flag); 802 return (T) this; 803 } 804 805 /** 806 * Sets the internal provider flag4 for the program. 807 * 808 * @param flag The forth internal provider flag for the program. 809 * @return This Builder object to allow for chaining of calls to builder methods. 810 * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG4 811 */ 812 public T setInternalProviderFlag4(long flag) { 813 mValues.put(ProgramColumns.COLUMN_INTERNAL_PROVIDER_FLAG4, flag); 814 return (T) this; 815 } 816 817 /** 818 * Sets the review rating score style used for {@link #setReviewRating}. 819 * 820 * @param reviewRatingStyle The reviewing rating style for the program. 821 * @return This Builder object to allow for chaining of calls to builder methods. 822 * 823 * @see Programs#COLUMN_REVIEW_RATING_STYLE 824 * @see Programs#REVIEW_RATING_STYLE_STARS 825 * @see Programs#REVIEW_RATING_STYLE_THUMBS_UP_DOWN 826 * @see Programs#REVIEW_RATING_STYLE_PERCENTAGE 827 */ 828 public T setReviewRatingStyle(@ReviewRatingStyle int reviewRatingStyle) { 829 mValues.put(ProgramColumns.COLUMN_REVIEW_RATING_STYLE, reviewRatingStyle); 830 return (T) this; 831 } 832 833 /** 834 * Sets the review rating score for this program. 835 * 836 * <p>The format of the value is dependent on the review rating style. If the style is 837 * based on "stars", the value should be a real number between 0.0 and 5.0. (e.g. "4.5") 838 * If the style is based on "thumbs up/down", the value should be two integers, one for 839 * thumbs-up count and the other for thumbs-down count, with a comma between them. 840 * (e.g. "200,40") If the style is base on "percentage", the value should be a 841 * real number between 0 and 100. (e.g. "99.9") 842 * 843 * @param reviewRating The value of the review rating for the program. 844 * @return This Builder object to allow for chaining of calls to builder methods. 845 * 846 * @see Programs#COLUMN_REVIEW_RATING 847 * @see Programs#COLUMN_REVIEW_RATING_STYLE 848 * @see Programs#REVIEW_RATING_STYLE_STARS 849 * @see Programs#REVIEW_RATING_STYLE_THUMBS_UP_DOWN 850 * @see Programs#REVIEW_RATING_STYLE_PERCENTAGE 851 */ 852 public T setReviewRating(String reviewRating) { 853 mValues.put(ProgramColumns.COLUMN_REVIEW_RATING, reviewRating); 854 return (T) this; 855 } 856 857 /** 858 * Sets a custom name for the season, if applicable. 859 * 860 * @param seasonTitle The season title for the program. 861 * @return This Builder object to allow for chaining of calls to builder methods. 862 * @see Programs#COLUMN_SEASON_TITLE 863 */ 864 public T setSeasonTitle(String seasonTitle) { 865 mValues.put(ProgramColumns.COLUMN_SEASON_TITLE, seasonTitle); 866 return (T) this; 867 } 868 } 869} 870