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