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 package android.support.v4.media.session; 17 18 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 19 20 import android.os.Build; 21 import android.os.Bundle; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.os.SystemClock; 25 import android.text.TextUtils; 26 import android.view.KeyEvent; 27 28 import androidx.annotation.IntDef; 29 import androidx.annotation.LongDef; 30 import androidx.annotation.Nullable; 31 import androidx.annotation.RestrictTo; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * Playback state for a {@link MediaSessionCompat}. This includes a state like 40 * {@link PlaybackStateCompat#STATE_PLAYING}, the current playback position, 41 * and the current control capabilities. 42 */ 43 public final class PlaybackStateCompat implements Parcelable { 44 45 /** 46 * @hide 47 */ 48 @RestrictTo(LIBRARY_GROUP) 49 @LongDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, 50 ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, 51 ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, 52 ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, 53 ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, 54 ACTION_SET_REPEAT_MODE, ACTION_SET_SHUFFLE_MODE, ACTION_SET_CAPTIONING_ENABLED}) 55 @Retention(RetentionPolicy.SOURCE) 56 public @interface Actions {} 57 58 /** 59 * @hide 60 */ 61 @RestrictTo(LIBRARY_GROUP) 62 @LongDef({ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS, 63 ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_PLAY_PAUSE}) 64 @Retention(RetentionPolicy.SOURCE) 65 public @interface MediaKeyAction {} 66 67 /** 68 * Indicates this session supports the stop command. 69 * 70 * @see Builder#setActions(long) 71 */ 72 public static final long ACTION_STOP = 1 << 0; 73 74 /** 75 * Indicates this session supports the pause command. 76 * 77 * @see Builder#setActions(long) 78 */ 79 public static final long ACTION_PAUSE = 1 << 1; 80 81 /** 82 * Indicates this session supports the play command. 83 * 84 * @see Builder#setActions(long) 85 */ 86 public static final long ACTION_PLAY = 1 << 2; 87 88 /** 89 * Indicates this session supports the rewind command. 90 * 91 * @see Builder#setActions(long) 92 */ 93 public static final long ACTION_REWIND = 1 << 3; 94 95 /** 96 * Indicates this session supports the previous command. 97 * 98 * @see Builder#setActions(long) 99 */ 100 public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; 101 102 /** 103 * Indicates this session supports the next command. 104 * 105 * @see Builder#setActions(long) 106 */ 107 public static final long ACTION_SKIP_TO_NEXT = 1 << 5; 108 109 /** 110 * Indicates this session supports the fast forward command. 111 * 112 * @see Builder#setActions(long) 113 */ 114 public static final long ACTION_FAST_FORWARD = 1 << 6; 115 116 /** 117 * Indicates this session supports the set rating command. 118 * 119 * @see Builder#setActions(long) 120 */ 121 public static final long ACTION_SET_RATING = 1 << 7; 122 123 /** 124 * Indicates this session supports the seek to command. 125 * 126 * @see Builder#setActions(long) 127 */ 128 public static final long ACTION_SEEK_TO = 1 << 8; 129 130 /** 131 * Indicates this session supports the play/pause toggle command. 132 * 133 * @see Builder#setActions(long) 134 */ 135 public static final long ACTION_PLAY_PAUSE = 1 << 9; 136 137 /** 138 * Indicates this session supports the play from media id command. 139 * 140 * @see Builder#setActions(long) 141 */ 142 public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10; 143 144 /** 145 * Indicates this session supports the play from search command. 146 * 147 * @see Builder#setActions(long) 148 */ 149 public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11; 150 151 /** 152 * Indicates this session supports the skip to queue item command. 153 * 154 * @see Builder#setActions(long) 155 */ 156 public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12; 157 158 /** 159 * Indicates this session supports the play from URI command. 160 * 161 * @see Builder#setActions(long) 162 */ 163 public static final long ACTION_PLAY_FROM_URI = 1 << 13; 164 165 /** 166 * Indicates this session supports the prepare command. 167 * 168 * @see Builder#setActions(long) 169 */ 170 public static final long ACTION_PREPARE = 1 << 14; 171 172 /** 173 * Indicates this session supports the prepare from media id command. 174 * 175 * @see Builder#setActions(long) 176 */ 177 public static final long ACTION_PREPARE_FROM_MEDIA_ID = 1 << 15; 178 179 /** 180 * Indicates this session supports the prepare from search command. 181 * 182 * @see Builder#setActions(long) 183 */ 184 public static final long ACTION_PREPARE_FROM_SEARCH = 1 << 16; 185 186 /** 187 * Indicates this session supports the prepare from URI command. 188 * 189 * @see Builder#setActions(long) 190 */ 191 public static final long ACTION_PREPARE_FROM_URI = 1 << 17; 192 193 /** 194 * Indicates this session supports the set repeat mode command. 195 * 196 * @see Builder#setActions(long) 197 */ 198 public static final long ACTION_SET_REPEAT_MODE = 1 << 18; 199 200 /** 201 * Indicates this session supports the set shuffle mode enabled command. 202 * 203 * @see Builder#setActions(long) 204 * @deprecated Use {@link #ACTION_SET_SHUFFLE_MODE} instead. 205 */ 206 @Deprecated 207 public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 1 << 19; 208 209 /** 210 * Indicates this session supports the set captioning enabled command. 211 * 212 * @see Builder#setActions(long) 213 */ 214 public static final long ACTION_SET_CAPTIONING_ENABLED = 1 << 20; 215 216 /** 217 * Indicates this session supports the set shuffle mode command. 218 * 219 * @see Builder#setActions(long) 220 */ 221 public static final long ACTION_SET_SHUFFLE_MODE = 1 << 21; 222 223 /** 224 * @hide 225 */ 226 @RestrictTo(LIBRARY_GROUP) 227 @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, 228 STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING, 229 STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM}) 230 @Retention(RetentionPolicy.SOURCE) 231 public @interface State {} 232 233 /** 234 * This is the default playback state and indicates that no media has been 235 * added yet, or the performer has been reset and has no content to play. 236 * 237 * @see Builder#setState 238 */ 239 public final static int STATE_NONE = 0; 240 241 /** 242 * State indicating this item is currently stopped. 243 * 244 * @see Builder#setState 245 */ 246 public final static int STATE_STOPPED = 1; 247 248 /** 249 * State indicating this item is currently paused. 250 * 251 * @see Builder#setState 252 */ 253 public final static int STATE_PAUSED = 2; 254 255 /** 256 * State indicating this item is currently playing. 257 * 258 * @see Builder#setState 259 */ 260 public final static int STATE_PLAYING = 3; 261 262 /** 263 * State indicating this item is currently fast forwarding. 264 * 265 * @see Builder#setState 266 */ 267 public final static int STATE_FAST_FORWARDING = 4; 268 269 /** 270 * State indicating this item is currently rewinding. 271 * 272 * @see Builder#setState 273 */ 274 public final static int STATE_REWINDING = 5; 275 276 /** 277 * State indicating this item is currently buffering and will begin playing 278 * when enough data has buffered. 279 * 280 * @see Builder#setState 281 */ 282 public final static int STATE_BUFFERING = 6; 283 284 /** 285 * State indicating this item is currently in an error state. The error 286 * code should also be set when entering this state. 287 * 288 * @see Builder#setState 289 * @see Builder#setErrorMessage(int, CharSequence) 290 */ 291 public final static int STATE_ERROR = 7; 292 293 /** 294 * State indicating the class doing playback is currently connecting to a 295 * route. Depending on the implementation you may return to the previous 296 * state when the connection finishes or enter {@link #STATE_NONE}. If 297 * the connection failed {@link #STATE_ERROR} should be used. 298 * <p> 299 * On devices earlier than API 21, this will appear as {@link #STATE_BUFFERING} 300 * </p> 301 * 302 * @see Builder#setState 303 */ 304 public final static int STATE_CONNECTING = 8; 305 306 /** 307 * State indicating the player is currently skipping to the previous item. 308 * 309 * @see Builder#setState 310 */ 311 public final static int STATE_SKIPPING_TO_PREVIOUS = 9; 312 313 /** 314 * State indicating the player is currently skipping to the next item. 315 * 316 * @see Builder#setState 317 */ 318 public final static int STATE_SKIPPING_TO_NEXT = 10; 319 320 /** 321 * State indicating the player is currently skipping to a specific item in 322 * the queue. 323 * <p> 324 * On devices earlier than API 21, this will appear as {@link #STATE_SKIPPING_TO_NEXT} 325 * </p> 326 * 327 * @see Builder#setState 328 */ 329 public final static int STATE_SKIPPING_TO_QUEUE_ITEM = 11; 330 331 /** 332 * Use this value for the position to indicate the position is not known. 333 */ 334 public final static long PLAYBACK_POSITION_UNKNOWN = -1; 335 336 /** 337 * @hide 338 */ 339 @RestrictTo(LIBRARY_GROUP) 340 @IntDef({REPEAT_MODE_INVALID, REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL, 341 REPEAT_MODE_GROUP}) 342 @Retention(RetentionPolicy.SOURCE) 343 public @interface RepeatMode {} 344 345 /** 346 * {@link MediaControllerCompat.TransportControls#getRepeatMode} returns this value 347 * when the session is not ready for providing its repeat mode. 348 */ 349 public static final int REPEAT_MODE_INVALID = -1; 350 351 /** 352 * Use this value with {@link MediaControllerCompat.TransportControls#setRepeatMode} 353 * to indicate that the playback will be stopped at the end of the playing media list. 354 */ 355 public static final int REPEAT_MODE_NONE = 0; 356 357 /** 358 * Use this value with {@link MediaControllerCompat.TransportControls#setRepeatMode} 359 * to indicate that the playback of the current playing media item will be repeated. 360 */ 361 public static final int REPEAT_MODE_ONE = 1; 362 363 /** 364 * Use this value with {@link MediaControllerCompat.TransportControls#setRepeatMode} 365 * to indicate that the playback of the playing media list will be repeated. 366 */ 367 public static final int REPEAT_MODE_ALL = 2; 368 369 /** 370 * Use this value with {@link MediaControllerCompat.TransportControls#setRepeatMode} 371 * to indicate that the playback of the playing media group will be repeated. 372 * A group is a logical block of media items which is specified in the section 5.7 of the 373 * Bluetooth AVRCP 1.6. 374 */ 375 public static final int REPEAT_MODE_GROUP = 3; 376 377 /** 378 * @hide 379 */ 380 @RestrictTo(LIBRARY_GROUP) 381 @IntDef({SHUFFLE_MODE_INVALID, SHUFFLE_MODE_NONE, SHUFFLE_MODE_ALL, SHUFFLE_MODE_GROUP}) 382 @Retention(RetentionPolicy.SOURCE) 383 public @interface ShuffleMode {} 384 385 /** 386 * {@link MediaControllerCompat.TransportControls#getShuffleMode} returns this value 387 * when the session is not ready for providing its shuffle mode. 388 */ 389 public static final int SHUFFLE_MODE_INVALID = -1; 390 391 /** 392 * Use this value with {@link MediaControllerCompat.TransportControls#setShuffleMode} 393 * to indicate that the media list will be played in order. 394 */ 395 public static final int SHUFFLE_MODE_NONE = 0; 396 397 /** 398 * Use this value with {@link MediaControllerCompat.TransportControls#setShuffleMode} 399 * to indicate that the media list will be played in shuffled order. 400 */ 401 public static final int SHUFFLE_MODE_ALL = 1; 402 403 /** 404 * Use this value with {@link MediaControllerCompat.TransportControls#setShuffleMode} 405 * to indicate that the media group will be played in shuffled order. 406 * A group is a logical block of media items which is specified in the section 5.7 of the 407 * Bluetooth AVRCP 1.6. 408 */ 409 public static final int SHUFFLE_MODE_GROUP = 2; 410 411 /** 412 * @hide 413 */ 414 @RestrictTo(LIBRARY_GROUP) 415 @IntDef({ERROR_CODE_UNKNOWN_ERROR, ERROR_CODE_APP_ERROR, ERROR_CODE_NOT_SUPPORTED, 416 ERROR_CODE_AUTHENTICATION_EXPIRED, ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED, 417 ERROR_CODE_CONCURRENT_STREAM_LIMIT, ERROR_CODE_PARENTAL_CONTROL_RESTRICTED, 418 ERROR_CODE_NOT_AVAILABLE_IN_REGION, ERROR_CODE_CONTENT_ALREADY_PLAYING, 419 ERROR_CODE_SKIP_LIMIT_REACHED, ERROR_CODE_ACTION_ABORTED, ERROR_CODE_END_OF_QUEUE}) 420 @Retention(RetentionPolicy.SOURCE) 421 public @interface ErrorCode {} 422 423 /** 424 * This is the default error code and indicates that none of the other error codes applies. 425 * The error code should be set when entering {@link #STATE_ERROR}. 426 */ 427 public static final int ERROR_CODE_UNKNOWN_ERROR = 0; 428 429 /** 430 * Error code when the application state is invalid to fulfill the request. 431 * The error code should be set when entering {@link #STATE_ERROR}. 432 */ 433 public static final int ERROR_CODE_APP_ERROR = 1; 434 435 /** 436 * Error code when the request is not supported by the application. 437 * The error code should be set when entering {@link #STATE_ERROR}. 438 */ 439 public static final int ERROR_CODE_NOT_SUPPORTED = 2; 440 441 /** 442 * Error code when the request cannot be performed because authentication has expired. 443 * The error code should be set when entering {@link #STATE_ERROR}. 444 */ 445 public static final int ERROR_CODE_AUTHENTICATION_EXPIRED = 3; 446 447 /** 448 * Error code when a premium account is required for the request to succeed. 449 * The error code should be set when entering {@link #STATE_ERROR}. 450 */ 451 public static final int ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED = 4; 452 453 /** 454 * Error code when too many concurrent streams are detected. 455 * The error code should be set when entering {@link #STATE_ERROR}. 456 */ 457 public static final int ERROR_CODE_CONCURRENT_STREAM_LIMIT = 5; 458 459 /** 460 * Error code when the content is blocked due to parental controls. 461 * The error code should be set when entering {@link #STATE_ERROR}. 462 */ 463 public static final int ERROR_CODE_PARENTAL_CONTROL_RESTRICTED = 6; 464 465 /** 466 * Error code when the content is blocked due to being regionally unavailable. 467 * The error code should be set when entering {@link #STATE_ERROR}. 468 */ 469 public static final int ERROR_CODE_NOT_AVAILABLE_IN_REGION = 7; 470 471 /** 472 * Error code when the requested content is already playing. 473 * The error code should be set when entering {@link #STATE_ERROR}. 474 */ 475 public static final int ERROR_CODE_CONTENT_ALREADY_PLAYING = 8; 476 477 /** 478 * Error code when the application cannot skip any more songs because skip limit is reached. 479 * The error code should be set when entering {@link #STATE_ERROR}. 480 */ 481 public static final int ERROR_CODE_SKIP_LIMIT_REACHED = 9; 482 483 /** 484 * Error code when the action is interrupted due to some external event. 485 * The error code should be set when entering {@link #STATE_ERROR}. 486 */ 487 public static final int ERROR_CODE_ACTION_ABORTED = 10; 488 489 /** 490 * Error code when the playback navigation (previous, next) is not possible because the queue 491 * was exhausted. 492 * The error code should be set when entering {@link #STATE_ERROR}. 493 */ 494 public static final int ERROR_CODE_END_OF_QUEUE = 11; 495 496 // KeyEvent constants only available on API 11+ 497 private static final int KEYCODE_MEDIA_PAUSE = 127; 498 private static final int KEYCODE_MEDIA_PLAY = 126; 499 500 /** 501 * Translates a given action into a matched key code defined in {@link KeyEvent}. The given 502 * action should be one of the following: 503 * <ul> 504 * <li>{@link PlaybackStateCompat#ACTION_PLAY}</li> 505 * <li>{@link PlaybackStateCompat#ACTION_PAUSE}</li> 506 * <li>{@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li> 507 * <li>{@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li> 508 * <li>{@link PlaybackStateCompat#ACTION_STOP}</li> 509 * <li>{@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li> 510 * <li>{@link PlaybackStateCompat#ACTION_REWIND}</li> 511 * <li>{@link PlaybackStateCompat#ACTION_PLAY_PAUSE}</li> 512 * </ul> 513 * 514 * @param action The action to be translated. 515 * 516 * @return the key code matched to the given action. 517 */ toKeyCode(@ediaKeyAction long action)518 public static int toKeyCode(@MediaKeyAction long action) { 519 if (action == ACTION_PLAY) { 520 return KEYCODE_MEDIA_PLAY; 521 } else if (action == ACTION_PAUSE) { 522 return KEYCODE_MEDIA_PAUSE; 523 } else if (action == ACTION_SKIP_TO_NEXT) { 524 return KeyEvent.KEYCODE_MEDIA_NEXT; 525 } else if (action == ACTION_SKIP_TO_PREVIOUS) { 526 return KeyEvent.KEYCODE_MEDIA_PREVIOUS; 527 } else if (action == ACTION_STOP) { 528 return KeyEvent.KEYCODE_MEDIA_STOP; 529 } else if (action == ACTION_FAST_FORWARD) { 530 return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 531 } else if (action == ACTION_REWIND) { 532 return KeyEvent.KEYCODE_MEDIA_REWIND; 533 } else if (action == ACTION_PLAY_PAUSE) { 534 return KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; 535 } 536 return KeyEvent.KEYCODE_UNKNOWN; 537 } 538 539 final int mState; 540 final long mPosition; 541 final long mBufferedPosition; 542 final float mSpeed; 543 final long mActions; 544 final int mErrorCode; 545 final CharSequence mErrorMessage; 546 final long mUpdateTime; 547 List<PlaybackStateCompat.CustomAction> mCustomActions; 548 final long mActiveItemId; 549 final Bundle mExtras; 550 551 private Object mStateObj; 552 PlaybackStateCompat(int state, long position, long bufferedPosition, float rate, long actions, int errorCode, CharSequence errorMessage, long updateTime, List<PlaybackStateCompat.CustomAction> customActions, long activeItemId, Bundle extras)553 PlaybackStateCompat(int state, long position, long bufferedPosition, 554 float rate, long actions, int errorCode, CharSequence errorMessage, long updateTime, 555 List<PlaybackStateCompat.CustomAction> customActions, 556 long activeItemId, Bundle extras) { 557 mState = state; 558 mPosition = position; 559 mBufferedPosition = bufferedPosition; 560 mSpeed = rate; 561 mActions = actions; 562 mErrorCode = errorCode; 563 mErrorMessage = errorMessage; 564 mUpdateTime = updateTime; 565 mCustomActions = new ArrayList<>(customActions); 566 mActiveItemId = activeItemId; 567 mExtras = extras; 568 } 569 PlaybackStateCompat(Parcel in)570 PlaybackStateCompat(Parcel in) { 571 mState = in.readInt(); 572 mPosition = in.readLong(); 573 mSpeed = in.readFloat(); 574 mUpdateTime = in.readLong(); 575 mBufferedPosition = in.readLong(); 576 mActions = in.readLong(); 577 mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 578 mCustomActions = in.createTypedArrayList(CustomAction.CREATOR); 579 mActiveItemId = in.readLong(); 580 mExtras = in.readBundle(); 581 // New attributes should be added at the end for backward compatibility. 582 mErrorCode = in.readInt(); 583 } 584 585 @Override toString()586 public String toString() { 587 StringBuilder bob = new StringBuilder("PlaybackState {"); 588 bob.append("state=").append(mState); 589 bob.append(", position=").append(mPosition); 590 bob.append(", buffered position=").append(mBufferedPosition); 591 bob.append(", speed=").append(mSpeed); 592 bob.append(", updated=").append(mUpdateTime); 593 bob.append(", actions=").append(mActions); 594 bob.append(", error code=").append(mErrorCode); 595 bob.append(", error message=").append(mErrorMessage); 596 bob.append(", custom actions=").append(mCustomActions); 597 bob.append(", active item id=").append(mActiveItemId); 598 bob.append("}"); 599 return bob.toString(); 600 } 601 602 @Override describeContents()603 public int describeContents() { 604 return 0; 605 } 606 607 @Override writeToParcel(Parcel dest, int flags)608 public void writeToParcel(Parcel dest, int flags) { 609 dest.writeInt(mState); 610 dest.writeLong(mPosition); 611 dest.writeFloat(mSpeed); 612 dest.writeLong(mUpdateTime); 613 dest.writeLong(mBufferedPosition); 614 dest.writeLong(mActions); 615 TextUtils.writeToParcel(mErrorMessage, dest, flags); 616 dest.writeTypedList(mCustomActions); 617 dest.writeLong(mActiveItemId); 618 dest.writeBundle(mExtras); 619 // New attributes should be added at the end for backward compatibility. 620 dest.writeInt(mErrorCode); 621 } 622 623 /** 624 * Get the current state of playback. One of the following: 625 * <ul> 626 * <li> {@link PlaybackStateCompat#STATE_NONE}</li> 627 * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li> 628 * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li> 629 * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li> 630 * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li> 631 * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li> 632 * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li> 633 * <li> {@link PlaybackStateCompat#STATE_ERROR}</li> 634 * <li> {@link PlaybackStateCompat#STATE_CONNECTING}</li> 635 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_PREVIOUS}</li> 636 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_NEXT}</li> 637 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_QUEUE_ITEM}</li> 638 */ 639 @State getState()640 public int getState() { 641 return mState; 642 } 643 644 /** 645 * Get the current playback position in ms. 646 */ getPosition()647 public long getPosition() { 648 return mPosition; 649 } 650 651 /** 652 * Get the current buffered position in ms. This is the farthest playback 653 * point that can be reached from the current position using only buffered 654 * content. 655 */ getBufferedPosition()656 public long getBufferedPosition() { 657 return mBufferedPosition; 658 } 659 660 /** 661 * Get the current playback speed as a multiple of normal playback. This 662 * should be negative when rewinding. A value of 1 means normal playback and 663 * 0 means paused. 664 * 665 * @return The current speed of playback. 666 */ getPlaybackSpeed()667 public float getPlaybackSpeed() { 668 return mSpeed; 669 } 670 671 /** 672 * Get the current actions available on this session. This should use a 673 * bitmask of the available actions. 674 * <ul> 675 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li> 676 * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li> 677 * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li> 678 * <li> {@link PlaybackStateCompat#ACTION_PLAY_PAUSE}</li> 679 * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li> 680 * <li> {@link PlaybackStateCompat#ACTION_STOP}</li> 681 * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li> 682 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li> 683 * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li> 684 * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li> 685 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}</li> 686 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH}</li> 687 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM}</li> 688 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_URI}</li> 689 * <li> {@link PlaybackStateCompat#ACTION_PREPARE}</li> 690 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_MEDIA_ID}</li> 691 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_SEARCH}</li> 692 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_URI}</li> 693 * <li> {@link PlaybackStateCompat#ACTION_SET_REPEAT_MODE}</li> 694 * <li> {@link PlaybackStateCompat#ACTION_SET_SHUFFLE_MODE}</li> 695 * <li> {@link PlaybackStateCompat#ACTION_SET_CAPTIONING_ENABLED}</li> 696 * </ul> 697 */ 698 @Actions getActions()699 public long getActions() { 700 return mActions; 701 } 702 703 /** 704 * Get the list of custom actions. 705 */ getCustomActions()706 public List<PlaybackStateCompat.CustomAction> getCustomActions() { 707 return mCustomActions; 708 } 709 710 /** 711 * Get the error code. This should be set when the state is 712 * {@link PlaybackStateCompat#STATE_ERROR}. 713 * 714 * @see #ERROR_CODE_UNKNOWN_ERROR 715 * @see #ERROR_CODE_APP_ERROR 716 * @see #ERROR_CODE_NOT_SUPPORTED 717 * @see #ERROR_CODE_AUTHENTICATION_EXPIRED 718 * @see #ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED 719 * @see #ERROR_CODE_CONCURRENT_STREAM_LIMIT 720 * @see #ERROR_CODE_PARENTAL_CONTROL_RESTRICTED 721 * @see #ERROR_CODE_NOT_AVAILABLE_IN_REGION 722 * @see #ERROR_CODE_CONTENT_ALREADY_PLAYING 723 * @see #ERROR_CODE_SKIP_LIMIT_REACHED 724 * @see #ERROR_CODE_ACTION_ABORTED 725 * @see #ERROR_CODE_END_OF_QUEUE 726 * @see #getErrorMessage() 727 */ 728 @ErrorCode getErrorCode()729 public int getErrorCode() { 730 return mErrorCode; 731 } 732 733 /** 734 * Get the user readable optional error message. This may be set when the state is 735 * {@link PlaybackStateCompat#STATE_ERROR}. 736 * 737 * @see #getErrorCode() 738 */ getErrorMessage()739 public CharSequence getErrorMessage() { 740 return mErrorMessage; 741 } 742 743 /** 744 * Get the elapsed real time at which position was last updated. If the 745 * position has never been set this will return 0; 746 * 747 * @return The last time the position was updated. 748 */ getLastPositionUpdateTime()749 public long getLastPositionUpdateTime() { 750 return mUpdateTime; 751 } 752 753 /** 754 * Get the id of the currently active item in the queue. If there is no 755 * queue or a queue is not supported by the session this will be 756 * {@link MediaSessionCompat.QueueItem#UNKNOWN_ID}. 757 * 758 * @return The id of the currently active item in the queue or 759 * {@link MediaSessionCompat.QueueItem#UNKNOWN_ID}. 760 */ getActiveQueueItemId()761 public long getActiveQueueItemId() { 762 return mActiveItemId; 763 } 764 765 /** 766 * Get any custom extras that were set on this playback state. 767 * 768 * @return The extras for this state or null. 769 */ getExtras()770 public @Nullable Bundle getExtras() { 771 return mExtras; 772 } 773 774 /** 775 * Creates an instance from a framework {@link android.media.session.PlaybackState} object. 776 * <p> 777 * This method is only supported on API 21+. 778 * </p> 779 * 780 * @param stateObj A {@link android.media.session.PlaybackState} object, or null if none. 781 * @return An equivalent {@link PlaybackStateCompat} object, or null if none. 782 */ fromPlaybackState(Object stateObj)783 public static PlaybackStateCompat fromPlaybackState(Object stateObj) { 784 if (stateObj != null && Build.VERSION.SDK_INT >= 21) { 785 List<Object> customActionObjs = PlaybackStateCompatApi21.getCustomActions(stateObj); 786 List<PlaybackStateCompat.CustomAction> customActions = null; 787 if (customActionObjs != null) { 788 customActions = new ArrayList<>(customActionObjs.size()); 789 for (Object customActionObj : customActionObjs) { 790 customActions.add(CustomAction.fromCustomAction(customActionObj)); 791 } 792 } 793 Bundle extras; 794 if (Build.VERSION.SDK_INT >= 22) { 795 extras = PlaybackStateCompatApi22.getExtras(stateObj); 796 } else { 797 extras = null; 798 } 799 PlaybackStateCompat state = new PlaybackStateCompat( 800 PlaybackStateCompatApi21.getState(stateObj), 801 PlaybackStateCompatApi21.getPosition(stateObj), 802 PlaybackStateCompatApi21.getBufferedPosition(stateObj), 803 PlaybackStateCompatApi21.getPlaybackSpeed(stateObj), 804 PlaybackStateCompatApi21.getActions(stateObj), 805 ERROR_CODE_UNKNOWN_ERROR, 806 PlaybackStateCompatApi21.getErrorMessage(stateObj), 807 PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj), 808 customActions, 809 PlaybackStateCompatApi21.getActiveQueueItemId(stateObj), 810 extras); 811 state.mStateObj = stateObj; 812 return state; 813 } else { 814 return null; 815 } 816 } 817 818 /** 819 * Gets the underlying framework {@link android.media.session.PlaybackState} object. 820 * <p> 821 * This method is only supported on API 21+. 822 * </p> 823 * 824 * @return An equivalent {@link android.media.session.PlaybackState} object, or null if none. 825 */ getPlaybackState()826 public Object getPlaybackState() { 827 if (mStateObj == null && Build.VERSION.SDK_INT >= 21) { 828 List<Object> customActions = null; 829 if (mCustomActions != null) { 830 customActions = new ArrayList<>(mCustomActions.size()); 831 for (PlaybackStateCompat.CustomAction customAction : mCustomActions) { 832 customActions.add(customAction.getCustomAction()); 833 } 834 } 835 if (Build.VERSION.SDK_INT >= 22) { 836 mStateObj = PlaybackStateCompatApi22.newInstance(mState, mPosition, 837 mBufferedPosition, 838 mSpeed, mActions, mErrorMessage, mUpdateTime, 839 customActions, mActiveItemId, mExtras); 840 } else { 841 //noinspection AndroidLintNewApi - NewApi lint fails to handle nested checks. 842 mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition, 843 mBufferedPosition, mSpeed, mActions, mErrorMessage, mUpdateTime, 844 customActions, mActiveItemId); 845 } 846 } 847 return mStateObj; 848 } 849 850 public static final Parcelable.Creator<PlaybackStateCompat> CREATOR = 851 new Parcelable.Creator<PlaybackStateCompat>() { 852 @Override 853 public PlaybackStateCompat createFromParcel(Parcel in) { 854 return new PlaybackStateCompat(in); 855 } 856 857 @Override 858 public PlaybackStateCompat[] newArray(int size) { 859 return new PlaybackStateCompat[size]; 860 } 861 }; 862 863 /** 864 * {@link PlaybackStateCompat.CustomAction CustomActions} can be used to 865 * extend the capabilities of the standard transport controls by exposing 866 * app specific actions to {@link MediaControllerCompat Controllers}. 867 */ 868 public static final class CustomAction implements Parcelable { 869 private final String mAction; 870 private final CharSequence mName; 871 private final int mIcon; 872 private final Bundle mExtras; 873 874 private Object mCustomActionObj; 875 876 /** 877 * Use {@link PlaybackStateCompat.CustomAction.Builder#build()}. 878 */ CustomAction(String action, CharSequence name, int icon, Bundle extras)879 CustomAction(String action, CharSequence name, int icon, Bundle extras) { 880 mAction = action; 881 mName = name; 882 mIcon = icon; 883 mExtras = extras; 884 } 885 CustomAction(Parcel in)886 CustomAction(Parcel in) { 887 mAction = in.readString(); 888 mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 889 mIcon = in.readInt(); 890 mExtras = in.readBundle(); 891 } 892 893 @Override writeToParcel(Parcel dest, int flags)894 public void writeToParcel(Parcel dest, int flags) { 895 dest.writeString(mAction); 896 TextUtils.writeToParcel(mName, dest, flags); 897 dest.writeInt(mIcon); 898 dest.writeBundle(mExtras); 899 } 900 901 @Override describeContents()902 public int describeContents() { 903 return 0; 904 } 905 906 /** 907 * Creates an instance from a framework 908 * {@link android.media.session.PlaybackState.CustomAction} object. 909 * <p> 910 * This method is only supported on API 21+. 911 * </p> 912 * 913 * @param customActionObj A {@link android.media.session.PlaybackState.CustomAction} object, 914 * or null if none. 915 * @return An equivalent {@link PlaybackStateCompat.CustomAction} object, or null if none. 916 */ fromCustomAction(Object customActionObj)917 public static PlaybackStateCompat.CustomAction fromCustomAction(Object customActionObj) { 918 if (customActionObj == null || Build.VERSION.SDK_INT < 21) { 919 return null; 920 } 921 922 PlaybackStateCompat.CustomAction customAction = new PlaybackStateCompat.CustomAction( 923 PlaybackStateCompatApi21.CustomAction.getAction(customActionObj), 924 PlaybackStateCompatApi21.CustomAction.getName(customActionObj), 925 PlaybackStateCompatApi21.CustomAction.getIcon(customActionObj), 926 PlaybackStateCompatApi21.CustomAction.getExtras(customActionObj)); 927 customAction.mCustomActionObj = customActionObj; 928 return customAction; 929 } 930 931 /** 932 * Gets the underlying framework {@link android.media.session.PlaybackState.CustomAction} 933 * object. 934 * <p> 935 * This method is only supported on API 21+. 936 * </p> 937 * 938 * @return An equivalent {@link android.media.session.PlaybackState.CustomAction} object, 939 * or null if none. 940 */ getCustomAction()941 public Object getCustomAction() { 942 if (mCustomActionObj != null || Build.VERSION.SDK_INT < 21) { 943 return mCustomActionObj; 944 } 945 946 mCustomActionObj = PlaybackStateCompatApi21.CustomAction.newInstance(mAction, 947 mName, mIcon, mExtras); 948 return mCustomActionObj; 949 } 950 951 public static final Parcelable.Creator<PlaybackStateCompat.CustomAction> CREATOR 952 = new Parcelable.Creator<PlaybackStateCompat.CustomAction>() { 953 954 @Override 955 public PlaybackStateCompat.CustomAction createFromParcel(Parcel p) { 956 return new PlaybackStateCompat.CustomAction(p); 957 } 958 959 @Override 960 public PlaybackStateCompat.CustomAction[] newArray(int size) { 961 return new PlaybackStateCompat.CustomAction[size]; 962 } 963 }; 964 965 /** 966 * Returns the action of the {@link CustomAction}. 967 * 968 * @return The action of the {@link CustomAction}. 969 */ getAction()970 public String getAction() { 971 return mAction; 972 } 973 974 /** 975 * Returns the display name of this action. e.g. "Favorite" 976 * 977 * @return The display name of this {@link CustomAction}. 978 */ getName()979 public CharSequence getName() { 980 return mName; 981 } 982 983 /** 984 * Returns the resource id of the icon in the {@link MediaSessionCompat 985 * Session's} package. 986 * 987 * @return The resource id of the icon in the {@link MediaSessionCompat 988 * Session's} package. 989 */ getIcon()990 public int getIcon() { 991 return mIcon; 992 } 993 994 /** 995 * Returns extras which provide additional application-specific 996 * information about the action, or null if none. These arguments are 997 * meant to be consumed by a {@link MediaControllerCompat} if it knows 998 * how to handle them. 999 * 1000 * @return Optional arguments for the {@link CustomAction}. 1001 */ getExtras()1002 public Bundle getExtras() { 1003 return mExtras; 1004 } 1005 1006 @Override toString()1007 public String toString() { 1008 return "Action:" + 1009 "mName='" + mName + 1010 ", mIcon=" + mIcon + 1011 ", mExtras=" + mExtras; 1012 } 1013 1014 /** 1015 * Builder for {@link CustomAction} objects. 1016 */ 1017 public static final class Builder { 1018 private final String mAction; 1019 private final CharSequence mName; 1020 private final int mIcon; 1021 private Bundle mExtras; 1022 1023 /** 1024 * Creates a {@link CustomAction} builder with the id, name, and 1025 * icon set. 1026 * 1027 * @param action The action of the {@link CustomAction}. 1028 * @param name The display name of the {@link CustomAction}. This 1029 * name will be displayed along side the action if the UI 1030 * supports it. 1031 * @param icon The icon resource id of the {@link CustomAction}. 1032 * This resource id must be in the same package as the 1033 * {@link MediaSessionCompat}. It will be displayed with 1034 * the custom action if the UI supports it. 1035 */ Builder(String action, CharSequence name, int icon)1036 public Builder(String action, CharSequence name, int icon) { 1037 if (TextUtils.isEmpty(action)) { 1038 throw new IllegalArgumentException( 1039 "You must specify an action to build a CustomAction."); 1040 } 1041 if (TextUtils.isEmpty(name)) { 1042 throw new IllegalArgumentException( 1043 "You must specify a name to build a CustomAction."); 1044 } 1045 if (icon == 0) { 1046 throw new IllegalArgumentException( 1047 "You must specify an icon resource id to build a CustomAction."); 1048 } 1049 mAction = action; 1050 mName = name; 1051 mIcon = icon; 1052 } 1053 1054 /** 1055 * Set optional extras for the {@link CustomAction}. These extras 1056 * are meant to be consumed by a {@link MediaControllerCompat} if it 1057 * knows how to handle them. Keys should be fully qualified (e.g. 1058 * "com.example.MY_ARG") to avoid collisions. 1059 * 1060 * @param extras Optional extras for the {@link CustomAction}. 1061 * @return this. 1062 */ setExtras(Bundle extras)1063 public Builder setExtras(Bundle extras) { 1064 mExtras = extras; 1065 return this; 1066 } 1067 1068 /** 1069 * Build and return the {@link CustomAction} instance with the 1070 * specified values. 1071 * 1072 * @return A new {@link CustomAction} instance. 1073 */ build()1074 public CustomAction build() { 1075 return new CustomAction(mAction, mName, mIcon, mExtras); 1076 } 1077 } 1078 } 1079 1080 /** 1081 * Builder for {@link PlaybackStateCompat} objects. 1082 */ 1083 public static final class Builder { 1084 private final List<PlaybackStateCompat.CustomAction> mCustomActions = new ArrayList<>(); 1085 1086 private int mState; 1087 private long mPosition; 1088 private long mBufferedPosition; 1089 private float mRate; 1090 private long mActions; 1091 private int mErrorCode; 1092 private CharSequence mErrorMessage; 1093 private long mUpdateTime; 1094 private long mActiveItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID; 1095 private Bundle mExtras; 1096 1097 /** 1098 * Create an empty Builder. 1099 */ Builder()1100 public Builder() { 1101 } 1102 1103 /** 1104 * Create a Builder using a {@link PlaybackStateCompat} instance to set the 1105 * initial values. 1106 * 1107 * @param source The playback state to copy. 1108 */ Builder(PlaybackStateCompat source)1109 public Builder(PlaybackStateCompat source) { 1110 mState = source.mState; 1111 mPosition = source.mPosition; 1112 mRate = source.mSpeed; 1113 mUpdateTime = source.mUpdateTime; 1114 mBufferedPosition = source.mBufferedPosition; 1115 mActions = source.mActions; 1116 mErrorCode = source.mErrorCode; 1117 mErrorMessage = source.mErrorMessage; 1118 if (source.mCustomActions != null) { 1119 mCustomActions.addAll(source.mCustomActions); 1120 } 1121 mActiveItemId = source.mActiveItemId; 1122 mExtras = source.mExtras; 1123 } 1124 1125 /** 1126 * Set the current state of playback. 1127 * <p> 1128 * The position must be in ms and indicates the current playback 1129 * position within the track. If the position is unknown use 1130 * {@link #PLAYBACK_POSITION_UNKNOWN}. 1131 * <p> 1132 * The rate is a multiple of normal playback and should be 0 when paused 1133 * and negative when rewinding. Normal playback rate is 1.0. 1134 * <p> 1135 * The state must be one of the following: 1136 * <ul> 1137 * <li> {@link PlaybackStateCompat#STATE_NONE}</li> 1138 * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li> 1139 * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li> 1140 * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li> 1141 * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li> 1142 * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li> 1143 * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li> 1144 * <li> {@link PlaybackStateCompat#STATE_ERROR}</li> 1145 * <li> {@link PlaybackStateCompat#STATE_CONNECTING}</li> 1146 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_PREVIOUS}</li> 1147 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_NEXT}</li> 1148 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_QUEUE_ITEM}</li> 1149 * </ul> 1150 * 1151 * @param state The current state of playback. 1152 * @param position The position in the current track in ms. 1153 * @param playbackSpeed The current rate of playback as a multiple of 1154 * normal playback. 1155 */ setState(@tate int state, long position, float playbackSpeed)1156 public Builder setState(@State int state, long position, float playbackSpeed) { 1157 return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime()); 1158 } 1159 1160 /** 1161 * Set the current state of playback. 1162 * <p> 1163 * The position must be in ms and indicates the current playback 1164 * position within the track. If the position is unknown use 1165 * {@link #PLAYBACK_POSITION_UNKNOWN}. 1166 * <p> 1167 * The rate is a multiple of normal playback and should be 0 when paused 1168 * and negative when rewinding. Normal playback rate is 1.0. 1169 * <p> 1170 * The state must be one of the following: 1171 * <ul> 1172 * <li> {@link PlaybackStateCompat#STATE_NONE}</li> 1173 * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li> 1174 * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li> 1175 * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li> 1176 * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li> 1177 * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li> 1178 * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li> 1179 * <li> {@link PlaybackStateCompat#STATE_ERROR}</li> 1180 * <li> {@link PlaybackStateCompat#STATE_CONNECTING}</li> 1181 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_PREVIOUS}</li> 1182 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_NEXT}</li> 1183 * <li> {@link PlaybackStateCompat#STATE_SKIPPING_TO_QUEUE_ITEM}</li> 1184 * </ul> 1185 * 1186 * @param state The current state of playback. 1187 * @param position The position in the current item in ms. 1188 * @param playbackSpeed The current speed of playback as a multiple of 1189 * normal playback. 1190 * @param updateTime The time in the {@link SystemClock#elapsedRealtime} 1191 * timebase that the position was updated at. 1192 * @return this 1193 */ setState(@tate int state, long position, float playbackSpeed, long updateTime)1194 public Builder setState(@State int state, long position, float playbackSpeed, 1195 long updateTime) { 1196 mState = state; 1197 mPosition = position; 1198 mUpdateTime = updateTime; 1199 mRate = playbackSpeed; 1200 return this; 1201 } 1202 1203 /** 1204 * Set the current buffered position in ms. This is the farthest 1205 * playback point that can be reached from the current position using 1206 * only buffered content. 1207 * 1208 * @return this 1209 */ setBufferedPosition(long bufferPosition)1210 public Builder setBufferedPosition(long bufferPosition) { 1211 mBufferedPosition = bufferPosition; 1212 return this; 1213 } 1214 1215 /** 1216 * Set the current capabilities available on this session. This should 1217 * use a bitmask of the available capabilities. 1218 * <ul> 1219 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li> 1220 * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li> 1221 * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li> 1222 * <li> {@link PlaybackStateCompat#ACTION_PLAY_PAUSE}</li> 1223 * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li> 1224 * <li> {@link PlaybackStateCompat#ACTION_STOP}</li> 1225 * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li> 1226 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li> 1227 * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li> 1228 * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li> 1229 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}</li> 1230 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH}</li> 1231 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM}</li> 1232 * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_URI}</li> 1233 * <li> {@link PlaybackStateCompat#ACTION_PREPARE}</li> 1234 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_MEDIA_ID}</li> 1235 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_SEARCH}</li> 1236 * <li> {@link PlaybackStateCompat#ACTION_PREPARE_FROM_URI}</li> 1237 * <li> {@link PlaybackStateCompat#ACTION_SET_REPEAT_MODE}</li> 1238 * <li> {@link PlaybackStateCompat#ACTION_SET_SHUFFLE_MODE}</li> 1239 * <li> {@link PlaybackStateCompat#ACTION_SET_CAPTIONING_ENABLED}</li> 1240 * </ul> 1241 * 1242 * @return this 1243 */ setActions(@ctions long capabilities)1244 public Builder setActions(@Actions long capabilities) { 1245 mActions = capabilities; 1246 return this; 1247 } 1248 1249 /** 1250 * Add a custom action to the playback state. Actions can be used to 1251 * expose additional functionality to {@link MediaControllerCompat 1252 * Controllers} beyond what is offered by the standard transport 1253 * controls. 1254 * <p> 1255 * e.g. start a radio station based on the current item or skip ahead by 1256 * 30 seconds. 1257 * 1258 * @param action An identifier for this action. It can be sent back to 1259 * the {@link MediaSessionCompat} through 1260 * {@link MediaControllerCompat.TransportControls#sendCustomAction(String, Bundle)}. 1261 * @param name The display name for the action. If text is shown with 1262 * the action or used for accessibility, this is what should 1263 * be used. 1264 * @param icon The resource action of the icon that should be displayed 1265 * for the action. The resource should be in the package of 1266 * the {@link MediaSessionCompat}. 1267 * @return this 1268 */ addCustomAction(String action, String name, int icon)1269 public Builder addCustomAction(String action, String name, int icon) { 1270 return addCustomAction(new PlaybackStateCompat.CustomAction(action, name, icon, null)); 1271 } 1272 1273 /** 1274 * Add a custom action to the playback state. Actions can be used to expose additional 1275 * functionality to {@link MediaControllerCompat Controllers} beyond what is offered 1276 * by the standard transport controls. 1277 * <p> 1278 * An example of an action would be to start a radio station based on the current item 1279 * or to skip ahead by 30 seconds. 1280 * 1281 * @param customAction The custom action to add to the {@link PlaybackStateCompat}. 1282 * @return this 1283 */ addCustomAction(PlaybackStateCompat.CustomAction customAction)1284 public Builder addCustomAction(PlaybackStateCompat.CustomAction customAction) { 1285 if (customAction == null) { 1286 throw new IllegalArgumentException( 1287 "You may not add a null CustomAction to PlaybackStateCompat."); 1288 } 1289 mCustomActions.add(customAction); 1290 return this; 1291 } 1292 1293 /** 1294 * Set the active item in the play queue by specifying its id. The 1295 * default value is {@link MediaSessionCompat.QueueItem#UNKNOWN_ID} 1296 * 1297 * @param id The id of the active item. 1298 * @return this 1299 */ setActiveQueueItemId(long id)1300 public Builder setActiveQueueItemId(long id) { 1301 mActiveItemId = id; 1302 return this; 1303 } 1304 1305 /** 1306 * Set a user readable error message. This should be set when the state 1307 * is {@link PlaybackStateCompat#STATE_ERROR}. 1308 * 1309 * @return this 1310 * @deprecated Use {@link #setErrorMessage(int, CharSequence)} instead. 1311 */ setErrorMessage(CharSequence errorMessage)1312 public Builder setErrorMessage(CharSequence errorMessage) { 1313 mErrorMessage = errorMessage; 1314 return this; 1315 } 1316 1317 /** 1318 * Set the error code with an optional user readable error message. This should be set when 1319 * the state is {@link PlaybackStateCompat#STATE_ERROR}. 1320 * 1321 * @param errorCode The errorCode to set. 1322 * @param errorMessage The user readable error message. Can be null. 1323 * @return this 1324 */ setErrorMessage(@rrorCode int errorCode, CharSequence errorMessage)1325 public Builder setErrorMessage(@ErrorCode int errorCode, CharSequence errorMessage) { 1326 mErrorCode = errorCode; 1327 mErrorMessage = errorMessage; 1328 return this; 1329 } 1330 1331 /** 1332 * Set any custom extras to be included with the playback state. 1333 * 1334 * @param extras The extras to include. 1335 * @return this 1336 */ setExtras(Bundle extras)1337 public Builder setExtras(Bundle extras) { 1338 mExtras = extras; 1339 return this; 1340 } 1341 1342 /** 1343 * Creates the playback state object. 1344 */ build()1345 public PlaybackStateCompat build() { 1346 return new PlaybackStateCompat(mState, mPosition, mBufferedPosition, 1347 mRate, mActions, mErrorCode, mErrorMessage, mUpdateTime, 1348 mCustomActions, mActiveItemId, mExtras); 1349 } 1350 } 1351 } 1352