TvContract.java revision cf9bec5bb6abfe134332d5004c1fee90901da62c
1/* 2 * Copyright (C) 2014 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 17package android.media.tv; 18 19import android.content.ComponentName; 20import android.content.ContentResolver; 21import android.content.ContentUris; 22import android.net.Uri; 23import android.provider.BaseColumns; 24 25import java.util.List; 26 27/** 28 * <p> 29 * The contract between the TV provider and applications. Contains definitions for the supported 30 * URIs and columns. 31 * </p> 32 * <h3>Overview</h3> 33 * <p> 34 * TvContract defines a basic database of TV content metadata such as channel and program 35 * information. The information is stored in {@link Channels} and {@link Programs} tables. 36 * </p> 37 * <ul> 38 * <li>A row in the {@link Channels} table represents information about a TV channel. The data 39 * format can vary greatly from standard to standard or according to service provider, thus 40 * the columns here are mostly comprised of basic entities that are usually seen to users 41 * regardless of standard such as channel number and name.</li> 42 * <li>A row in the {@link Programs} table represents a set of data describing a TV program such 43 * as program title and start time.</li> 44 * </ul> 45 */ 46public final class TvContract { 47 /** The authority for the TV provider. */ 48 public static final String AUTHORITY = "android.media.tv"; 49 50 private static final String PATH_CHANNEL = "channel"; 51 private static final String PATH_PROGRAM = "program"; 52 private static final String PATH_INPUT = "input"; 53 54 /** 55 * An optional query, update or delete URI parameter that allows the caller to specify start 56 * time (in milliseconds since the epoch) to filter programs. 57 * 58 * @hide 59 */ 60 public static final String PARAM_START_TIME = "start_time"; 61 62 /** 63 * An optional query, update or delete URI parameter that allows the caller to specify end time 64 * (in milliseconds since the epoch) to filter programs. 65 * 66 * @hide 67 */ 68 public static final String PARAM_END_TIME = "end_time"; 69 70 /** 71 * A query, update or delete URI parameter that allows the caller to operate on all or 72 * browsable-only channels. If set to "true", the rows that contain non-browsable channels are 73 * not affected. 74 * 75 * @hide 76 */ 77 public static final String PARAM_BROWSABLE_ONLY = "browsable_only"; 78 79 /** 80 * Builds a URI that points to a specific channel. 81 * 82 * @param channelId The ID of the channel to point to. 83 */ 84 public static final Uri buildChannelUri(long channelId) { 85 return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId); 86 } 87 88 /** 89 * Builds a URI that points to a channel logo. See {@link Channels.Logo}. 90 * 91 * @param channelId The ID of the channel whose logo is pointed to. 92 */ 93 public static final Uri buildChannelLogoUri(long channelId) { 94 return buildChannelLogoUri(buildChannelUri(channelId)); 95 } 96 97 /** 98 * Builds a URI that points to a channel logo. See {@link Channels.Logo}. 99 * 100 * @param channelUri The URI of the channel whose logo is pointed to. 101 */ 102 public static final Uri buildChannelLogoUri(Uri channelUri) { 103 if (!PATH_CHANNEL.equals(channelUri.getPathSegments().get(0))) { 104 throw new IllegalArgumentException("Not a channel: " + channelUri); 105 } 106 return Uri.withAppendedPath(channelUri, Channels.Logo.CONTENT_DIRECTORY); 107 } 108 109 /** 110 * Builds a URI that points to all browsable channels from a given TV input. 111 * 112 * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that 113 * implements the given TV input. 114 */ 115 public static final Uri buildChannelsUriForInput(ComponentName name) { 116 return buildChannelsUriForInput(name, true); 117 } 118 119 /** 120 * Builds a URI that points to all or browsable-only channels from a given TV input. 121 * 122 * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that 123 * implements the given TV input. 124 * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set 125 * to {@code false} the URI points to all channels regardless of whether they are 126 * browsable or not. 127 */ 128 public static final Uri buildChannelsUriForInput(ComponentName name, boolean browsableOnly) { 129 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY) 130 .appendPath(PATH_INPUT).appendPath(name.getPackageName()) 131 .appendPath(name.getClassName()).appendPath(PATH_CHANNEL) 132 .appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)).build(); 133 } 134 135 /** 136 * Builds a URI that points to a specific program. 137 * 138 * @param programId The ID of the program to point to. 139 */ 140 public static final Uri buildProgramUri(long programId) { 141 return ContentUris.withAppendedId(Programs.CONTENT_URI, programId); 142 } 143 144 /** 145 * Builds a URI that points to all programs on a given channel. 146 * 147 * @param channelId The ID of the channel to return programs for. 148 */ 149 public static final Uri buildProgramsUriForChannel(long channelId) { 150 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY) 151 .appendPath(PATH_CHANNEL).appendPath(String.valueOf(channelId)) 152 .appendPath(PATH_PROGRAM).build(); 153 } 154 155 /** 156 * Builds a URI that points to all programs on a given channel. 157 * 158 * @param channelUri The URI of the channel to return programs for. 159 */ 160 public static final Uri buildProgramsUriForChannel(Uri channelUri) { 161 if (!PATH_CHANNEL.equals(channelUri.getPathSegments().get(0))) { 162 throw new IllegalArgumentException("Not a channel: " + channelUri); 163 } 164 return buildProgramsUriForChannel(ContentUris.parseId(channelUri)); 165 } 166 167 /** 168 * Builds a URI that points to programs on a specific channel whose schedules overlap with the 169 * given time frame. 170 * 171 * @param channelId The ID of the channel to return programs for. 172 * @param startTime The start time used to filter programs. The returned programs should have 173 * {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time. 174 * @param endTime The end time used to filter programs. The returned programs should have 175 * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time. 176 */ 177 public static final Uri buildProgramsUriForChannel(long channelId, long startTime, 178 long endTime) { 179 Uri uri = buildProgramsUriForChannel(channelId); 180 return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime)) 181 .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build(); 182 } 183 184 /** 185 * Builds a URI that points to programs on a specific channel whose schedules overlap with the 186 * given time frame. 187 * 188 * @param channelUri The URI of the channel to return programs for. 189 * @param startTime The start time used to filter programs. The returned programs should have 190 * {@link Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this time. 191 * @param endTime The end time used to filter programs. The returned programs should have 192 * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time. 193 */ 194 public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime, 195 long endTime) { 196 if (!PATH_CHANNEL.equals(channelUri.getPathSegments().get(0))) { 197 throw new IllegalArgumentException("Not a channel: " + channelUri); 198 } 199 return buildProgramsUriForChannel(ContentUris.parseId(channelUri), startTime, endTime); 200 } 201 202 /** 203 * Builds a URI that points to a specific program the user watched. 204 * 205 * @param watchedProgramId The ID of the watched program to point to. 206 * @hide 207 */ 208 public static final Uri buildWatchedProgramUri(long watchedProgramId) { 209 return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId); 210 } 211 212 /** 213 * Extracts the {@link Channels#COLUMN_PACKAGE_NAME} from a given URI. 214 * 215 * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or 216 * {@link #buildChannelsUriForInput(ComponentName, boolean)}. 217 * @hide 218 */ 219 public static final String getPackageName(Uri channelsUri) { 220 final List<String> paths = channelsUri.getPathSegments(); 221 if (paths.size() < 4) { 222 throw new IllegalArgumentException("Not channels: " + channelsUri); 223 } 224 if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) { 225 throw new IllegalArgumentException("Not channels: " + channelsUri); 226 } 227 return paths.get(1); 228 } 229 230 /** 231 * Extracts the {@link Channels#COLUMN_SERVICE_NAME} from a given URI. 232 * 233 * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or 234 * {@link #buildChannelsUriForInput(ComponentName, boolean)}. 235 * @hide 236 */ 237 public static final String getServiceName(Uri channelsUri) { 238 final List<String> paths = channelsUri.getPathSegments(); 239 if (paths.size() < 4) { 240 throw new IllegalArgumentException("Not channels: " + channelsUri); 241 } 242 if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) { 243 throw new IllegalArgumentException("Not channels: " + channelsUri); 244 } 245 return paths.get(2); 246 } 247 248 /** 249 * Extracts the {@link Channels#_ID} from a given URI. 250 * 251 * @param programsUri A URI constructed by {@link #buildProgramsUriForChannel(Uri)} or 252 * {@link #buildProgramsUriForChannel(Uri, long, long)}. 253 * @hide 254 */ 255 public static final String getChannelId(Uri programsUri) { 256 final List<String> paths = programsUri.getPathSegments(); 257 if (paths.size() < 3) { 258 throw new IllegalArgumentException("Not programs: " + programsUri); 259 } 260 if (!PATH_CHANNEL.equals(paths.get(0)) || !PATH_PROGRAM.equals(paths.get(2))) { 261 throw new IllegalArgumentException("Not programs: " + programsUri); 262 } 263 return paths.get(1); 264 } 265 266 267 private TvContract() {} 268 269 /** 270 * Common base for the tables of TV channels/programs. 271 */ 272 public interface BaseTvColumns extends BaseColumns { 273 /** 274 * The name of the package that owns a row in each table. 275 * <p> 276 * The TV provider fills it in with the name of the package that provides the initial data 277 * of that row. If the package is later uninstalled, the rows it owns are automatically 278 * removed from the tables. 279 * </p><p> 280 * Type: TEXT 281 * </p> 282 */ 283 public static final String COLUMN_PACKAGE_NAME = "package_name"; 284 } 285 286 /** Column definitions for the TV channels table. */ 287 public static final class Channels implements BaseTvColumns { 288 289 /** The content:// style URI for this table. */ 290 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" 291 + PATH_CHANNEL); 292 293 /** The MIME type of a directory of TV channels. */ 294 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel"; 295 296 /** The MIME type of a single TV channel. */ 297 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel"; 298 299 /** A generic channel type. */ 300 public static final int TYPE_OTHER = 0x0; 301 302 /** The channel type for NTSC. */ 303 public static final int TYPE_NTSC = 0x1; 304 305 /** The channel type for PAL. */ 306 public static final int TYPE_PAL = 0x2; 307 308 /** The channel type for SECAM. */ 309 public static final int TYPE_SECAM = 0x3; 310 311 /** The special channel type used for pass-through inputs such as HDMI. */ 312 public static final int TYPE_PASSTHROUGH = 0x00010000; 313 314 /** The channel type for DVB-T (terrestrial). */ 315 public static final int TYPE_DVB_T = 0x00020000; 316 317 /** The channel type for DVB-T2 (terrestrial). */ 318 public static final int TYPE_DVB_T2 = 0x00020001; 319 320 /** The channel type for DVB-S (satellite). */ 321 public static final int TYPE_DVB_S = 0x00020100; 322 323 /** The channel type for DVB-S2 (satellite). */ 324 public static final int TYPE_DVB_S2 = 0x00020101; 325 326 /** The channel type for DVB-C (cable). */ 327 public static final int TYPE_DVB_C = 0x00020200; 328 329 /** The channel type for DVB-C2 (cable). */ 330 public static final int TYPE_DVB_C2 = 0x00020201; 331 332 /** The channel type for DVB-H (handheld). */ 333 public static final int TYPE_DVB_H = 0x00020300; 334 335 /** The channel type for DVB-SH (satellite). */ 336 public static final int TYPE_DVB_SH = 0x00020400; 337 338 /** The channel type for ATSC (terrestrial). */ 339 public static final int TYPE_ATSC_T = 0x00030000; 340 341 /** The channel type for ATSC (cable). */ 342 public static final int TYPE_ATSC_C = 0x00030200; 343 344 /** The channel type for ATSC-M/H (mobile/handheld). */ 345 public static final int TYPE_ATSC_M_H = 0x00030300; 346 347 /** The channel type for ISDB-T (terrestrial). */ 348 public static final int TYPE_ISDB_T = 0x00040000; 349 350 /** The channel type for ISDB-Tb (Brazil). */ 351 public static final int TYPE_ISDB_TB = 0x00040100; 352 353 /** The channel type for ISDB-S (satellite). */ 354 public static final int TYPE_ISDB_S = 0x00040200; 355 356 /** The channel type for ISDB-C (cable). */ 357 public static final int TYPE_ISDB_C = 0x00040300; 358 359 /** The channel type for 1seg (handheld). */ 360 public static final int TYPE_1SEG = 0x00040400; 361 362 /** The channel type for DTMB (terrestrial). */ 363 public static final int TYPE_DTMB = 0x00050000; 364 365 /** The channel type for CMMB (handheld). */ 366 public static final int TYPE_CMMB = 0x00050100; 367 368 /** The channel type for T-DMB (terrestrial). */ 369 public static final int TYPE_T_DMB = 0x00060000; 370 371 /** The channel type for S-DMB (satellite). */ 372 public static final int TYPE_S_DMB = 0x00060100; 373 374 /** A generic service type. */ 375 public static final int SERVICE_TYPE_OTHER = 0x0; 376 377 /** The service type for regular TV channels that have both audio and video. */ 378 public static final int SERVICE_TYPE_AUDIO_VIDEO = 0x1; 379 380 /** The service type for radio channels that have audio only. */ 381 public static final int SERVICE_TYPE_AUDIO = 0x2; 382 383 /** 384 * The name of the {@link TvInputService} subclass that provides this TV channel. This 385 * should be a fully qualified class name (such as, "com.example.project.TvInputService"). 386 * <p> 387 * This is a required field. 388 * </p><p> 389 * Type: TEXT 390 * </p> 391 */ 392 public static final String COLUMN_SERVICE_NAME = "service_name"; 393 394 /** 395 * The predefined type of this TV channel. 396 * <p> 397 * This is primarily used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the 398 * current channel conforms to, with an exception being {@link #TYPE_PASSTHROUGH}, which is 399 * a special channel type used only by pass-through inputs such as HDMI. The value should 400 * match to one of the followings: {@link #TYPE_OTHER}, {@link #TYPE_PASSTHROUGH}, 401 * {@link #TYPE_DVB_T}, {@link #TYPE_DVB_T2}, {@link #TYPE_DVB_S}, {@link #TYPE_DVB_S2}, 402 * {@link #TYPE_DVB_C}, {@link #TYPE_DVB_C2}, {@link #TYPE_DVB_H}, {@link #TYPE_DVB_SH}, 403 * {@link #TYPE_ATSC_T}, {@link #TYPE_ATSC_C}, {@link #TYPE_ATSC_M_H}, {@link #TYPE_ISDB_T}, 404 * {@link #TYPE_ISDB_TB}, {@link #TYPE_ISDB_S}, {@link #TYPE_ISDB_C} {@link #TYPE_1SEG}, 405 * {@link #TYPE_DTMB}, {@link #TYPE_CMMB}, {@link #TYPE_T_DMB}, {@link #TYPE_S_DMB} 406 * </p><p> 407 * This is a required field. 408 * </p><p> 409 * Type: INTEGER 410 * </p> 411 */ 412 public static final String COLUMN_TYPE = "type"; 413 414 /** 415 * The predefined service type of this TV channel. 416 * <p> 417 * This is primarily used to indicate whether the current channel is a regular TV channel or 418 * a radio-like channel. Use the same coding for {@code service_type} in the underlying 419 * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB 420 * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER}, 421 * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO} 422 * </p><p> 423 * This is a required field. 424 * </p><p> 425 * Type: INTEGER 426 * </p> 427 */ 428 public static final String COLUMN_SERVICE_TYPE = "service_type"; 429 430 /** 431 * The original network ID of this TV channel. 432 * <p> 433 * This is used to identify the originating delivery system, if applicable. Use the same 434 * coding for {@code original_network_id} in the underlying broadcast standard if it is 435 * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be 436 * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID}, 437 * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a 438 * unique 3-tuple identification {{@link #COLUMN_ORIGINAL_NETWORK_ID}, 439 * {@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}} for its channels. 440 * </p><p> 441 * This is a required field if the channel cannot be uniquely identified by a 2-tuple 442 * {{@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}}. 443 * </p><p> 444 * Type: INTEGER 445 * </p> 446 */ 447 public static final String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id"; 448 449 /** 450 * The transport stream ID of this channel. 451 * <p> 452 * This is used to identify the Transport Stream that contains the current channel from any 453 * other multiplex within a network, if applicable. Use the same coding for 454 * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via 455 * the MPEG Transport Stream as is the case for many digital broadcast standards. 456 * </p><p> 457 * This is a required field if the current channel is transmitted via the MPEG Transport 458 * Stream. 459 * </p><p> 460 * Type: INTEGER 461 * </p> 462 */ 463 public static final String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id"; 464 465 /** 466 * The service ID of this channel. 467 * <p> 468 * This is used to identify the current service (roughly equivalent to channel) from any 469 * other service within the Transport Stream, if applicable. Use the same coding for 470 * {@code service_id} in the underlying broadcast standard if it is defined there (e.g. ETSI 471 * EN 300 468 and ARIB STD-B10) or {@code program_number} (which usually has the same value 472 * as {@code service_id}) in ISO/IEC 13818-1 if the channel is transmitted via the MPEG 473 * Transport Stream. 474 * </p><p> 475 * This is a required field if the current channel is transmitted via the MPEG Transport 476 * Stream. 477 * </p><p> 478 * Type: INTEGER 479 * </p> 480 */ 481 public static final String COLUMN_SERVICE_ID = "service_id"; 482 483 /** 484 * The channel number that is displayed to the user. 485 * <p> 486 * The format can vary depending on broadcast standard and product specification. 487 * </p><p> 488 * Type: TEXT 489 * </p> 490 */ 491 public static final String COLUMN_DISPLAY_NUMBER = "display_number"; 492 493 /** 494 * The channel name that is displayed to the user. 495 * <p> 496 * A call sign is a good candidate to use for this purpose but any name that helps the user 497 * recognize the current channel will be enough. Can also be empty depending on broadcast 498 * standard. 499 * </p><p> 500 * Type: TEXT 501 * </p> 502 */ 503 public static final String COLUMN_DISPLAY_NAME = "display_name"; 504 505 /** 506 * The description of this TV channel. 507 * <p> 508 * Can be empty initially. 509 * </p><p> 510 * Type: TEXT 511 * </p> 512 */ 513 public static final String COLUMN_DESCRIPTION = "description"; 514 515 /** 516 * The flag indicating whether this TV channel is browsable or not. 517 * <p> 518 * A value of 1 indicates the channel is included in the channel list that applications use 519 * to browse channels, a value of 0 indicates the channel is not included in the list. If 520 * not specified, this value is set to 1 (browsable) by default. 521 * </p><p> 522 * Type: INTEGER (boolean) 523 * </p> 524 */ 525 public static final String COLUMN_BROWSABLE = "browsable"; 526 527 /** 528 * The flag indicating whether this TV channel is searchable or not. 529 * <p> 530 * In some regions, it is not allowed to surface search results for a given channel without 531 * broadcaster's consent. This is used to impose such restriction. A value of 1 indicates 532 * the channel is searchable and can be included in search results, a value of 0 indicates 533 * the channel and its TV programs are hidden from search. If not specified, this value is 534 * set to 1 (searchable) by default. 535 * </p> 536 * <p> 537 * Type: INTEGER (boolean) 538 * </p> 539 */ 540 public static final String COLUMN_SEARCHABLE = "searchable"; 541 542 /** 543 * The flag indicating whether this TV channel is locked or not. 544 * <p> 545 * This is primarily used for alternative parental control to prevent unauthorized users 546 * from watching the current channel regardless of the content rating. A value of 1 547 * indicates the channel is locked and the user is required to enter passcode to unlock it 548 * in order to watch the current program from the channel, a value of 0 indicates the 549 * channel is not locked thus the user is not prompted to enter passcode If not specified, 550 * this value is set to 0 (not locked) by default. 551 * </p><p> 552 * Type: INTEGER (boolean) 553 * </p> 554 * @hide 555 */ 556 public static final String COLUMN_LOCKED = "locked"; 557 558 /** 559 * Internal data used by individual TV input services. 560 * <p> 561 * This is internal to the provider that inserted it, and should not be decoded by other 562 * apps. 563 * </p><p> 564 * Type: BLOB 565 * </p> 566 */ 567 public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; 568 569 /** 570 * The version number of this row entry used by TV input services. 571 * <p> 572 * This is best used by sync adapters to identify the rows to update. The number can be 573 * defined by individual TV input services. One may assign the same value as 574 * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are 575 * coming from a TV broadcast. 576 * </p><p> 577 * Type: INTEGER 578 * </p> 579 */ 580 public static final String COLUMN_VERSION_NUMBER = "version_number"; 581 582 private Channels() {} 583 584 /** 585 * A sub-directory of a single TV channel that represents its primary logo. 586 * <p> 587 * To access this directory, append {@link Channels.Logo#CONTENT_DIRECTORY} to the raw 588 * channel URI. The resulting URI represents an image file, and should be interacted 589 * using ContentResolver.openAssetFileDescriptor. 590 * </p> 591 * <p> 592 * Note that this sub-directory also supports opening the logo as an asset file in write 593 * mode. Callers can create or replace the primary logo associated with this channel by 594 * opening the asset file and writing the full-size photo contents into it. When the file 595 * is closed, the image will be parsed, sized down if necessary, and stored. 596 * </p> 597 * <p> 598 * Usage example: 599 * <pre> 600 * public void writeChannelLogo(long channelId, byte[] logo) { 601 * Uri channelLogoUri = TvContract.buildChannelLogoUri(channelId); 602 * try { 603 * AssetFileDescriptor fd = 604 * getContentResolver().openAssetFileDescriptor(channelLogoUri, "rw"); 605 * OutputStream os = fd.createOutputStream(); 606 * os.write(logo); 607 * os.close(); 608 * fd.close(); 609 * } catch (IOException e) { 610 * // Handle error cases. 611 * } 612 * } 613 * </pre> 614 * </p> 615 */ 616 public static final class Logo { 617 618 /** 619 * The directory twig for this sub-table. 620 */ 621 public static final String CONTENT_DIRECTORY = "logo"; 622 623 private Logo() {} 624 } 625 } 626 627 /** Column definitions for the TV programs table. */ 628 public static final class Programs implements BaseTvColumns { 629 630 /** The content:// style URI for this table. */ 631 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" 632 + PATH_PROGRAM); 633 634 /** The MIME type of a directory of TV programs. */ 635 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program"; 636 637 /** The MIME type of a single TV program. */ 638 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; 639 640 /** 641 * The ID of the TV channel that contains this TV program. 642 * <p> 643 * This is a part of the channel URI and matches to {@link BaseColumns#_ID}. 644 * </p><p> 645 * Type: INTEGER (long) 646 * </p> 647 */ 648 public static final String COLUMN_CHANNEL_ID = "channel_id"; 649 650 /** 651 * The title of this TV program. 652 * <p> 653 * Type: TEXT 654 * </p> 655 **/ 656 public static final String COLUMN_TITLE = "title"; 657 658 /** 659 * The start time of this TV program, in milliseconds since the epoch. 660 * <p> 661 * Type: INTEGER (long) 662 * </p> 663 */ 664 public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; 665 666 /** 667 * The end time of this TV program, in milliseconds since the epoch. 668 * <p> 669 * Type: INTEGER (long) 670 * </p> 671 */ 672 public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; 673 674 /** 675 * The comma-separated genre string of this TV program. 676 * <p> 677 * Use the same language appeared in the underlying broadcast standard, if applicable. (For 678 * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or 679 * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. 680 * </p><p> 681 * Type: TEXT 682 * </p> 683 */ 684 public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre"; 685 686 /** 687 * The comma-separated canonical genre string of this TV program. 688 * <p> 689 * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()} 690 * to create a text that can be stored in this column. Use {@link Genres#decode 691 * Genres.decode()} to get the canonical genre strings from the text stored in this column. 692 * </p><p> 693 * Type: TEXT 694 * </p> 695 * @see Genres 696 */ 697 public static final String COLUMN_CANONICAL_GENRE = "canonical_genre"; 698 699 /** 700 * The short description of this TV program that is displayed to the user by default. 701 * <p> 702 * It is recommended to limit the length of the descriptions to 256 characters. 703 * </p><p> 704 * Type: TEXT 705 * </p> 706 */ 707 public static final String COLUMN_SHORT_DESCRIPTION = "short_description"; 708 709 /** 710 * The detailed, lengthy description of this TV program that is displayed only when the user 711 * wants to see more information. 712 * <p> 713 * TV input services should leave this field empty if they have no additional details beyond 714 * {@link #COLUMN_SHORT_DESCRIPTION}. 715 * </p><p> 716 * Type: TEXT 717 * </p> 718 */ 719 public static final String COLUMN_LONG_DESCRIPTION = "long_description"; 720 721 /** 722 * The comma-separated audio languages of this TV program. 723 * <p> 724 * This is used to describe available audio languages included in the program. Use 725 * 3-character language code as specified by ISO 639-2. 726 * </p><p> 727 * Type: TEXT 728 * </p> 729 */ 730 public static final String COLUMN_AUDIO_LANGUAGE = "audio_language"; 731 732 /** 733 * The URI for the poster art of this TV program. 734 * <p> 735 * Can be empty. 736 * </p><p> 737 * Type: TEXT 738 * </p> 739 */ 740 public static final String COLUMN_POSTER_ART_URI = "poster_art_uri"; 741 742 /** 743 * The URI for the thumbnail of this TV program. 744 * <p> 745 * Can be empty. 746 * </p><p> 747 * Type: TEXT 748 * </p> 749 */ 750 public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; 751 752 /** 753 * Internal data used by individual TV input services. 754 * <p> 755 * This is internal to the provider that inserted it, and should not be decoded by other 756 * apps. 757 * </p><p> 758 * Type: BLOB 759 * </p> 760 */ 761 public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; 762 763 /** 764 * The version number of this row entry used by TV input services. 765 * <p> 766 * This is best used by sync adapters to identify the rows to update. The number can be 767 * defined by individual TV input services. One may assign the same value as 768 * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV 769 * broadcast. 770 * </p><p> 771 * Type: INTEGER 772 * </p> 773 */ 774 public static final String COLUMN_VERSION_NUMBER = "version_number"; 775 776 private Programs() {} 777 778 /** Canonical genres for TV programs. */ 779 public static final class Genres { 780 /** The genre for Family/Kids. */ 781 public static final String FAMILY_KIDS = "Family/Kids"; 782 783 /** The genre for Sports. */ 784 public static final String SPORTS = "Sports"; 785 786 /** The genre for Shopping. */ 787 public static final String SHOPPING = "Shopping"; 788 789 /** The genre for Movies. */ 790 public static final String MOVIES = "Movies"; 791 792 /** The genre for Comedy. */ 793 public static final String COMEDY = "Comedy"; 794 795 /** The genre for Travel. */ 796 public static final String TRAVEL = "Travel"; 797 798 /** The genre for Drama. */ 799 public static final String DRAMA = "Drama"; 800 801 /** The genre for Education. */ 802 public static final String EDUCATION = "Education"; 803 804 /** The genre for Animal/Wildlife. */ 805 public static final String ANIMAL_WILDLIFE = "Animal/Wildlife"; 806 807 /** The genre for News. */ 808 public static final String NEWS = "News"; 809 810 /** The genre for Gaming. */ 811 public static final String GAMING = "Gaming"; 812 813 private Genres() {} 814 815 /** 816 * Encodes canonical genre strings to a text that can be put into the database. 817 * 818 * @param genres Canonical genre strings. Use the strings defined in this class. 819 * @return an encoded genre string that can be inserted into the 820 * {@link #COLUMN_CANONICAL_GENRE} column. 821 */ 822 public static String encode(String... genres) { 823 StringBuilder sb = new StringBuilder(); 824 String separator = ""; 825 for (String genre : genres) { 826 sb.append(separator).append(genre); 827 separator = ","; 828 } 829 return sb.toString(); 830 } 831 832 /** 833 * Decodes the canonical genre strings from the text stored in the database. 834 * 835 * @param genres The encoded genre string retrieved from the 836 * {@link #COLUMN_CANONICAL_GENRE} column. 837 * @return canonical genre strings. 838 */ 839 public static String[] decode(String genres) { 840 return genres.split("\\s*,\\s*"); 841 } 842 } 843 } 844 845 /** 846 * Column definitions for the TV programs that the user watched. Applications do not have access 847 * to this table. 848 * 849 * @hide 850 */ 851 public static final class WatchedPrograms implements BaseColumns { 852 853 /** The content:// style URI for this table. */ 854 public static final Uri CONTENT_URI = 855 Uri.parse("content://" + AUTHORITY + "/watched_program"); 856 857 /** The MIME type of a directory of watched programs. */ 858 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program"; 859 860 /** The MIME type of a single item in this table. */ 861 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program"; 862 863 /** 864 * The UTC time that the user started watching this TV program, in milliseconds since the 865 * epoch. 866 * <p> 867 * Type: INTEGER (long) 868 * </p> 869 */ 870 public static final String COLUMN_WATCH_START_TIME_UTC_MILLIS = 871 "watch_start_time_utc_millis"; 872 873 /** 874 * The UTC time that the user stopped watching this TV program, in milliseconds since the 875 * epoch. 876 * <p> 877 * Type: INTEGER (long) 878 * </p> 879 */ 880 public static final String COLUMN_WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis"; 881 882 /** 883 * The channel ID that contains this TV program. 884 * <p> 885 * Type: INTEGER (long) 886 * </p> 887 */ 888 public static final String COLUMN_CHANNEL_ID = "channel_id"; 889 890 /** 891 * The title of this TV program. 892 * <p> 893 * Type: TEXT 894 * </p> 895 */ 896 public static final String COLUMN_TITLE = "title"; 897 898 /** 899 * The start time of this TV program, in milliseconds since the epoch. 900 * <p> 901 * Type: INTEGER (long) 902 * </p> 903 */ 904 public static final String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; 905 906 /** 907 * The end time of this TV program, in milliseconds since the epoch. 908 * <p> 909 * Type: INTEGER (long) 910 * </p> 911 */ 912 public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; 913 914 /** 915 * The description of this TV program. 916 * <p> 917 * Type: TEXT 918 * </p> 919 */ 920 public static final String COLUMN_DESCRIPTION = "description"; 921 922 private WatchedPrograms() {} 923 } 924} 925