1a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown/* 2a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Copyright (C) 2013 The Android Open Source Project 3a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 4a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * you may not use this file except in compliance with the License. 6a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * You may obtain a copy of the License at 7a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 8a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 10a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Unless required by applicable law or agreed to in writing, software 11a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * See the License for the specific language governing permissions and 14a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * limitations under the License. 15a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 16a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownpackage android.support.v7.media; 17a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 18a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.app.PendingIntent; 19a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.content.BroadcastReceiver; 20a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.content.Context; 21a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.content.Intent; 22a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.content.IntentFilter; 23a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.net.Uri; 24a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.os.Bundle; 25a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownimport android.util.Log; 26a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 27a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown/** 28a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * A helper class for playing media on remote routes using the remote playback protocol 29a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * defined by {@link MediaControlIntent}. 30a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 31a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The client maintains session state and offers a simplified interface for issuing 32a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * remote playback media control intents to a single route. 33a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 34a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 35a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brownpublic class RemotePlaybackClient { 36a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private static final String TAG = "RemotePlaybackClient"; 37a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 38a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 39a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final Context mContext; 40a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final MediaRouter.RouteInfo mRoute; 41a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final StatusReceiver mStatusReceiver; 42a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final PendingIntent mItemStatusPendingIntent; 43a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final PendingIntent mSessionStatusPendingIntent; 44a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 45a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private boolean mRouteSupportsRemotePlayback; 46a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private boolean mRouteSupportsQueuing; 47a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private boolean mRouteSupportsSessionManagement; 48a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 49a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private String mSessionId; 50a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private StatusCallback mStatusCallback; 51a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 52a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 53a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Creates a remote playback client for a route. 54a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 55a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param route The media route. 56a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 57a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public RemotePlaybackClient(Context context, MediaRouter.RouteInfo route) { 58a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (context == null) { 59a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("context must not be null"); 60a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 61a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (route == null) { 62a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("route must not be null"); 63a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 64a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 65a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mContext = context; 66a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRoute = route; 67a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 68a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown IntentFilter statusFilter = new IntentFilter(); 69a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown statusFilter.addAction(StatusReceiver.ACTION_ITEM_STATUS_CHANGED); 70a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown statusFilter.addAction(StatusReceiver.ACTION_SESSION_STATUS_CHANGED); 71a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mStatusReceiver = new StatusReceiver(); 72a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown context.registerReceiver(mStatusReceiver, statusFilter); 73a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 74a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent itemStatusIntent = new Intent(StatusReceiver.ACTION_ITEM_STATUS_CHANGED); 75a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown itemStatusIntent.setPackage(context.getPackageName()); 76a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mItemStatusPendingIntent = PendingIntent.getBroadcast( 77a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown context, 0, itemStatusIntent, 0); 78a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 79a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent sessionStatusIntent = new Intent(StatusReceiver.ACTION_SESSION_STATUS_CHANGED); 80a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown sessionStatusIntent.setPackage(context.getPackageName()); 81a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mSessionStatusPendingIntent = PendingIntent.getBroadcast( 82a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown context, 0, sessionStatusIntent, 0); 83a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 84a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown detectFeatures(); 85a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 86a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 87a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 88a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Releases resources owned by the client. 89a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 90a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void release() { 91a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mContext.unregisterReceiver(mStatusReceiver); 92a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 93a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 94a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 95a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Returns true if the route supports remote playback. 96a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 97a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * If the route does not support remote playback, then none of the functionality 98a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * offered by the client will be available. 99a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 100a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * This method returns true if the route supports all of the following 101a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * actions: {@link MediaControlIntent#ACTION_PLAY play}, 102a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_SEEK seek}, 103a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_GET_STATUS get status}, 104a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_PAUSE pause}, 105a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_RESUME resume}, 106a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_STOP stop}. 107a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 108a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 109a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @return True if remote playback is supported. 110a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 111a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public boolean isRemotePlaybackSupported() { 112a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mRouteSupportsRemotePlayback; 113a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 114a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 115a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 116a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Returns true if the route supports queuing features. 117a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 118a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * If the route does not support queuing, then at most one media item can be played 119a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * at a time and the {@link #enqueue} method will not be available. 120a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 121a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * This method returns true if the route supports all of the basic remote playback 122a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * actions and all of the following actions: 123a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_ENQUEUE enqueue}, 124a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_REMOVE remove}. 125a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 126a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 127a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @return True if queuing is supported. Implies {@link #isRemotePlaybackSupported} 128a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * is also true. 129a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 130a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 131a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 132a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public boolean isQueuingSupported() { 133a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mRouteSupportsQueuing; 134a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 135a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 136a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 137a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Returns true if the route supports session management features. 138a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 139a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * If the route does not support session management, then the session will 140a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * not be created until the first media item is played. 141a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 142a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * This method returns true if the route supports all of the basic remote playback 143a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * actions and all of the following actions: 144a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_START_SESSION start session}, 145a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_GET_SESSION_STATUS get session status}, 146a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_END_SESSION end session}. 147a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 148a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 149a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @return True if session management is supported. 150a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Implies {@link #isRemotePlaybackSupported} is also true. 151a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 152a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 153a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 154a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public boolean isSessionManagementSupported() { 155a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mRouteSupportsSessionManagement; 156a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 157a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 158a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 159a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Gets the current session id if there is one. 160a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 161a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @return The current session id, or null if none. 162a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 163a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public String getSessionId() { 164a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mSessionId; 165a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 166a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 167a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 168a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sets the current session id. 169a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 170a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * It is usually not necessary to set the session id explicitly since 171a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * it is created as a side-effect of other requests such as 172a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link #play}, {@link #enqueue}, and {@link #startSession}. 173a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 174a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 175a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The new session id, or null if none. 176a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 177a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void setSessionId(String sessionId) { 178a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (mSessionId != sessionId 179a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && (mSessionId == null || !mSessionId.equals(sessionId))) { 180a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 181a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Session id is now: " + sessionId); 182a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 183a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mSessionId = sessionId; 184a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (mStatusCallback != null) { 185a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mStatusCallback.onSessionChanged(sessionId); 186a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 187a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 188a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 189a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 190a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 191a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Returns true if the client currently has a session. 192a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 193a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Equivalent to checking whether {@link #getSessionId} returns a non-null result. 194a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 195a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 196a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @return True if there is a current session. 197a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 198a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public boolean hasSession() { 199a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mSessionId != null; 200a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 201a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 202a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 203a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sets a callback that should receive status updates when the state of 204a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * media sessions or media items created by this instance of the remote 205a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * playback client changes. 206a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 207a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The callback should be set before the session is created or any play 208a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * commands are issued. 209a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 210a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 211a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback The callback to set. May be null to remove the previous callback. 212a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 213a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void setStatusCallback(StatusCallback callback) { 214a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mStatusCallback = callback; 215a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 216a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 217a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 218a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to play a media item. 219a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 220a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Clears the queue and starts playing the new item immediately. If the queue 221a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * was previously paused, then it is resumed as a side-effect of this request. 222a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 223a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If no session is available, then 224a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * one is created implicitly. 225a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 226a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_PLAY ACTION_PLAY} for 227a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 228a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 229a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 230a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param contentUri The content Uri to play. 231a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param mimeType The mime type of the content, or null if unknown. 232a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param positionMillis The initial content position for the item in milliseconds, 233a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * or <code>0</code> to start at the beginning. 234a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param metadata The media item metadata bundle, or null if none. 235a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 236a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_PLAY} intent, or null if none. 237a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 238a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 239a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 240a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support remote playback. 241a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 242a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_PLAY 243a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 244a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 245a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void play(Uri contentUri, String mimeType, Bundle metadata, 246a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown long positionMillis, Bundle extras, ItemActionCallback callback) { 247a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown playOrEnqueue(contentUri, mimeType, metadata, positionMillis, 248a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown extras, callback, MediaControlIntent.ACTION_PLAY); 249a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 250a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 251a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 252a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to enqueue a media item. 253a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 254a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Enqueues a new item to play. If the queue was previously paused, then will 255a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * remain paused. 256a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 257a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If no session is available, then 258a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * one is created implicitly. 259a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 260a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_ENQUEUE ACTION_ENQUEUE} for 261a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 262a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 263a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 264a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param contentUri The content Uri to enqueue. 265a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param mimeType The mime type of the content, or null if unknown. 266a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param positionMillis The initial content position for the item in milliseconds, 267a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * or <code>0</code> to start at the beginning. 268a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param metadata The media item metadata bundle, or null if none. 269a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 270a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_ENQUEUE} intent, or null if none. 271a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 272a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 273a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 274a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support queuing. 275a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 276a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_ENQUEUE 277a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 278a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isQueuingSupported 279a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 280a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void enqueue(Uri contentUri, String mimeType, Bundle metadata, 281a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown long positionMillis, Bundle extras, ItemActionCallback callback) { 282a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown playOrEnqueue(contentUri, mimeType, metadata, positionMillis, 283a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown extras, callback, MediaControlIntent.ACTION_ENQUEUE); 284a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 285a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 286a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void playOrEnqueue(Uri contentUri, String mimeType, Bundle metadata, 287a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown long positionMillis, Bundle extras, 288a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown final ItemActionCallback callback, String action) { 289a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (contentUri == null) { 290a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("contentUri must not be null"); 291a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 292a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfRemotePlaybackNotSupported(); 293a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) { 294a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfQueuingNotSupported(); 295a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 296a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 297a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(action); 298a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.setDataAndType(contentUri, mimeType); 299a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER, 300a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mItemStatusPendingIntent); 301a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (metadata != null) { 302a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_ITEM_METADATA, metadata); 303a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 304a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (positionMillis != 0) { 305a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, positionMillis); 306a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 307a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performItemAction(intent, mSessionId, null, extras, callback); 308a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 309a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 310a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 311a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to seek to a new position in a media item. 312a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 313a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Seeks to a new position. If the queue was previously paused then it 314a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * remains paused but the item's new position is still remembered. 315a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 316a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. 317a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 318a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_SEEK ACTION_SEEK} for 319a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 320a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 321a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 322a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemId The item id. 323a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param positionMillis The new content position for the item in milliseconds, 324a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * or <code>0</code> to start at the beginning. 325a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 326a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_SEEK} intent, or null if none. 327a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 328a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 329a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 330a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 331a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 332a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_SEEK 333a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 334a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 335a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void seek(String itemId, long positionMillis, Bundle extras, 336a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown ItemActionCallback callback) { 337a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemId == null) { 338a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("itemId must not be null"); 339a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 340a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 341a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 342a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_SEEK); 343a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, positionMillis); 344a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performItemAction(intent, mSessionId, itemId, extras, callback); 345a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 346a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 347a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 348a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to get the status of a media item. 349a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 350a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. 351a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 352a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_GET_STATUS ACTION_GET_STATUS} for 353a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 354a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 355a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 356a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemId The item id. 357a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 358a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_GET_STATUS} intent, or null if none. 359a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 360a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 361a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 362a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 363a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 364a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_GET_STATUS 365a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 366a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 367a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void getStatus(String itemId, Bundle extras, ItemActionCallback callback) { 368a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemId == null) { 369a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("itemId must not be null"); 370a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 371a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 372a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 373a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_GET_STATUS); 374a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performItemAction(intent, mSessionId, itemId, extras, callback); 375a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 376a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 377a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 378a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to remove a media item from the queue. 379a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 380a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. 381a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 382a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_REMOVE ACTION_REMOVE} for 383a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 384a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 385a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 386a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemId The item id. 387a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 388a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_REMOVE} intent, or null if none. 389a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 390a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 391a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 392a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 393a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support queuing. 394a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 395a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_REMOVE 396a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 397a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isQueuingSupported 398a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 399a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void remove(String itemId, Bundle extras, ItemActionCallback callback) { 400a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemId == null) { 401a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalArgumentException("itemId must not be null"); 402a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 403a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfQueuingNotSupported(); 404a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 405a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 406a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_REMOVE); 407a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performItemAction(intent, mSessionId, itemId, extras, callback); 408a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 409a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 410a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 411a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to pause media playback. 412a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 413a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If playback is already paused 414a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * then the request has no effect. 415a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 416a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_PAUSE ACTION_PAUSE} for 417a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 418a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 419a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 420a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 421a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_PAUSE} intent, or null if none. 422a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 423a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 424a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 425a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 426a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 427a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_PAUSE 428a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 429a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 430a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void pause(Bundle extras, SessionActionCallback callback) { 431a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 432a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 433a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_PAUSE); 434a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, mSessionId, extras, callback); 435a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 436a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 437a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 438a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to resume (unpause) media playback. 439a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 440a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If playback is not paused 441a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * then the request has no effect. 442a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 443a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_RESUME ACTION_RESUME} for 444a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 445a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 446a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 447a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 448a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_RESUME} intent, or null if none. 449a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 450a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 451a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 452a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 453a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 454a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_RESUME 455a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 456a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 457a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void resume(Bundle extras, SessionActionCallback callback) { 458a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 459a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 460a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_RESUME); 461a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, mSessionId, extras, callback); 462a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 463a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 464a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 465a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to stop media playback and clear the media playback queue. 466a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 467a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If the queue is already 468a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * empty then the request has no effect. 469a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 470a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_STOP ACTION_STOP} for 471a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * more information about the semantics of this request. 472a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 473a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 474a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 475a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_STOP} intent, or null if none. 476a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 477a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 478a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 479a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 480a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 481a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_STOP 482a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 483a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 484a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void stop(Bundle extras, SessionActionCallback callback) { 485a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 486a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 487a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_STOP); 488a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, mSessionId, extras, callback); 489a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 490a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 491a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 492a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to start a new media playback session. 493a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 494a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The application must wait for the callback to indicate that this request 495a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * is complete before issuing other requests that affect the session. If this 496a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * request is successful then the previous session will be invalidated. 497a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 498a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_START_SESSION ACTION_START_SESSION} 499a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * for more information about the semantics of this request. 500a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 501a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 502a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 503a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_START_SESSION} intent, or null if none. 504a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 505a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 506a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 507a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support session management. 508a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 509a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_START_SESSION 510a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 511a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isSessionManagementSupported 512a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 513a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void startSession(Bundle extras, SessionActionCallback callback) { 514a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfSessionManagementNotSupported(); 515a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 516a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_START_SESSION); 517a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_SESSION_STATUS_UPDATE_RECEIVER, 518a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mSessionStatusPendingIntent); 519a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, null, extras, callback); 520a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 521a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 522a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 523a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to get the status of the media playback session. 524a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 525a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. 526a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 527a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_GET_SESSION_STATUS 528a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * ACTION_GET_SESSION_STATUS} for more information about the semantics of this request. 529a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 530a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 531a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 532a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_GET_SESSION_STATUS} intent, or null if none. 533a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 534a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 535a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 536a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 537a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support session management. 538a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 539a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_GET_SESSION_STATUS 540a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 541a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isSessionManagementSupported 542a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 543a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void getSessionStatus(Bundle extras, SessionActionCallback callback) { 544a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfSessionManagementNotSupported(); 545a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 546a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 547a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_GET_SESSION_STATUS); 548a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, mSessionId, extras, callback); 549a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 550a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 551a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 552a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Sends a request to end the media playback session. 553a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * <p> 554a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * The request is issued in the current session. If this request is successful, 555a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * the {@link #getSessionId session id property} will be set to null after 556a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * the callback is invoked. 557a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p><p> 558a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Please refer to {@link MediaControlIntent#ACTION_END_SESSION ACTION_END_SESSION} 559a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * for more information about the semantics of this request. 560a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * </p> 561a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 562a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param extras A bundle of extra arguments to be added to the 563a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * {@link MediaControlIntent#ACTION_END_SESSION} intent, or null if none. 564a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param callback A callback to invoke when the request has been 565a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * processed, or null if none. 566a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 567a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws IllegalStateException if there is no current session. 568a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @throws UnsupportedOperationException if the route does not support session management. 569a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 570a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see MediaControlIntent#ACTION_END_SESSION 571a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isRemotePlaybackSupported 572a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @see #isSessionManagementSupported 573a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 574a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void endSession(Bundle extras, SessionActionCallback callback) { 575a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfSessionManagementNotSupported(); 576a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throwIfNoCurrentSession(); 577a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 578a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Intent intent = new Intent(MediaControlIntent.ACTION_END_SESSION); 579a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown performSessionAction(intent, mSessionId, extras, callback); 580a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 581a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 582a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void performItemAction(final Intent intent, 583a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown final String sessionId, final String itemId, 584a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Bundle extras, final ItemActionCallback callback) { 585a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 586a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionId != null) { 587a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sessionId); 588a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 589a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemId != null) { 590a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, itemId); 591a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 592a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (extras != null) { 593a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtras(extras); 594a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 595a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown logRequest(intent); 596a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRoute.sendControlRequest(intent, new MediaRouter.ControlRequestCallback() { 597a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown @Override 598a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onResult(Bundle data) { 599a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (data != null) { 600a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String sessionIdResult = inferMissingResult(sessionId, 601a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getString(MediaControlIntent.EXTRA_SESSION_ID)); 602a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaSessionStatus sessionStatus = MediaSessionStatus.fromBundle( 603a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getBundle(MediaControlIntent.EXTRA_SESSION_STATUS)); 604a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String itemIdResult = inferMissingResult(itemId, 605a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getString(MediaControlIntent.EXTRA_ITEM_ID)); 606a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaItemStatus itemStatus = MediaItemStatus.fromBundle( 607a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS)); 608a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown adoptSession(sessionIdResult); 609a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionIdResult != null && itemIdResult != null && itemStatus != null) { 610a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 611a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Received result from " + intent.getAction() 612a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ": data=" + bundleToString(data) 613a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionId=" + sessionIdResult 614a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionStatus=" + sessionStatus 615a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", itemId=" + itemIdResult 616a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", itemStatus=" + itemStatus); 617a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 618a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown callback.onResult(data, sessionIdResult, sessionStatus, 619a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown itemIdResult, itemStatus); 620a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 621a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 622a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 623a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown handleInvalidResult(intent, callback, data); 624a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 625a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 626a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown @Override 627a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onError(String error, Bundle data) { 628a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown handleError(intent, callback, error, data); 629a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 630a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown }); 631a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 632a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 633a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void performSessionAction(final Intent intent, final String sessionId, 634a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Bundle extras, final SessionActionCallback callback) { 635a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 636a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionId != null) { 637a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sessionId); 638a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 639a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (extras != null) { 640a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.putExtras(extras); 641a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 642a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown logRequest(intent); 643a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRoute.sendControlRequest(intent, new MediaRouter.ControlRequestCallback() { 644a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown @Override 645a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onResult(Bundle data) { 646a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (data != null) { 647a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String sessionIdResult = inferMissingResult(sessionId, 648a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getString(MediaControlIntent.EXTRA_SESSION_ID)); 649a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaSessionStatus sessionStatus = MediaSessionStatus.fromBundle( 650a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown data.getBundle(MediaControlIntent.EXTRA_SESSION_STATUS)); 651a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown adoptSession(sessionIdResult); 652a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionIdResult != null) { 653a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 654a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Received result from " + intent.getAction() 655a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ": data=" + bundleToString(data) 656a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionId=" + sessionIdResult 657a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionStatus=" + sessionStatus); 658a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 659a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown try { 660a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown callback.onResult(data, sessionIdResult, sessionStatus); 661a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } finally { 662a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (intent.getAction().equals(MediaControlIntent.ACTION_END_SESSION) 663a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && sessionIdResult.equals(mSessionId)) { 664a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown setSessionId(null); 665a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 666a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 667a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 668a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 669a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 670a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown handleInvalidResult(intent, callback, data); 671a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 672a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 673a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown @Override 674a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onError(String error, Bundle data) { 675a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown handleError(intent, callback, error, data); 676a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 677a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown }); 678a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 679a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 680a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void adoptSession(String sessionId) { 681a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionId != null) { 682a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown setSessionId(sessionId); 683a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 684a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 685a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 686a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void handleInvalidResult(Intent intent, ActionCallback callback, 687a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Bundle data) { 688a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Received invalid result data from " + intent.getAction() 689a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ": data=" + bundleToString(data)); 690a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown callback.onError(null, MediaControlIntent.ERROR_UNKNOWN, data); 691a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 692a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 693a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void handleError(Intent intent, ActionCallback callback, 694a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String error, Bundle data) { 695a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown final int code; 696a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (data != null) { 697a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown code = data.getInt(MediaControlIntent.EXTRA_ERROR_CODE, 698a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaControlIntent.ERROR_UNKNOWN); 699a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } else { 700a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown code = MediaControlIntent.ERROR_UNKNOWN; 701a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 702a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 703a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Received error from " + intent.getAction() 704a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ": error=" + error 705a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", code=" + code 706a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", data=" + bundleToString(data)); 707a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 708a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown callback.onError(error, code, data); 709a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 710a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 711a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void detectFeatures() { 712a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRouteSupportsRemotePlayback = routeSupportsAction(MediaControlIntent.ACTION_PLAY) 713a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_SEEK) 714a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_GET_STATUS) 715a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_PAUSE) 716a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_RESUME) 717a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_STOP); 718a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRouteSupportsQueuing = mRouteSupportsRemotePlayback 719a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_ENQUEUE) 720a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_REMOVE); 721a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mRouteSupportsSessionManagement = mRouteSupportsRemotePlayback 722a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_START_SESSION) 723a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_GET_SESSION_STATUS) 724a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown && routeSupportsAction(MediaControlIntent.ACTION_END_SESSION); 725a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 726a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 727a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private boolean routeSupportsAction(String action) { 728a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return mRoute.supportsControlAction(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK, action); 729a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 730a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 731a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void throwIfRemotePlaybackNotSupported() { 732a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (!mRouteSupportsRemotePlayback) { 733a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new UnsupportedOperationException("The route does not support remote playback."); 734a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 735a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 736a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 737a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void throwIfQueuingNotSupported() { 738a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (!mRouteSupportsQueuing) { 739a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new UnsupportedOperationException("The route does not support queuing."); 740a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 741a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 742a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 743a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void throwIfSessionManagementNotSupported() { 744a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (!mRouteSupportsSessionManagement) { 745a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new UnsupportedOperationException("The route does not support " 746a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + "session management."); 747a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 748a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 749a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 750a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private void throwIfNoCurrentSession() { 751a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (mSessionId == null) { 752a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown throw new IllegalStateException("There is no current session."); 753a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 754a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 755a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 756a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private static String inferMissingResult(String request, String result) { 757a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (result == null) { 758a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown // Result is missing. 759a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return request; 760a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 761a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (request == null || request.equals(result)) { 762a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown // Request didn't specify a value or result matches request. 763a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return result; 764a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 765a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown // Result conflicts with request. 766a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return null; 767a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 768a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 769a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private static void logRequest(Intent intent) { 770a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 771a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Sending request: " + intent); 772a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 773a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 774a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 775a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private static String bundleToString(Bundle bundle) { 776a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (bundle != null) { 777a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown bundle.size(); // force bundle to be unparcelled 778a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return bundle.toString(); 779a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 780a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return "null"; 781a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 782a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 783a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown private final class StatusReceiver extends BroadcastReceiver { 784a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static final String ACTION_ITEM_STATUS_CHANGED = 785a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown "android.support.v7.media.actions.ACTION_ITEM_STATUS_CHANGED"; 786a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static final String ACTION_SESSION_STATUS_CHANGED = 787a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown "android.support.v7.media.actions.ACTION_SESSION_STATUS_CHANGED"; 788a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 789a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown @Override 790a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onReceive(Context context, Intent intent) { 791a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String sessionId = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 792a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionId == null || !sessionId.equals(mSessionId)) { 793a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Discarding spurious status callback " 794a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + "with missing or invalid session id: sessionId=" + sessionId); 795a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 796a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 797a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 798a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaSessionStatus sessionStatus = MediaSessionStatus.fromBundle( 799a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.getBundleExtra(MediaControlIntent.EXTRA_SESSION_STATUS)); 800a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String action = intent.getAction(); 801a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (action.equals(ACTION_ITEM_STATUS_CHANGED)) { 802a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String itemId = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); 803a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemId == null) { 804a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Discarding spurious status callback with missing item id."); 805a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 806a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 807a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 808a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown MediaItemStatus itemStatus = MediaItemStatus.fromBundle( 809a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_STATUS)); 810a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (itemStatus == null) { 811a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Discarding spurious status callback with missing item status."); 812a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 813a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 814a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 815a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 816a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Received item status callback: sessionId=" + sessionId 817a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionStatus=" + sessionStatus 818a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", itemId=" + itemId 819a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", itemStatus=" + itemStatus); 820a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 821a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 822a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (mStatusCallback != null) { 823a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mStatusCallback.onItemStatusChanged(intent.getExtras(), 824a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown sessionId, sessionStatus, itemId, itemStatus); 825a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 826a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } else if (action.equals(ACTION_SESSION_STATUS_CHANGED)) { 827a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (sessionStatus == null) { 828a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.w(TAG, "Discarding spurious media status callback with " 829a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown +"missing session status."); 830a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown return; 831a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 832a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 833a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (DEBUG) { 834a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown Log.d(TAG, "Received session status callback: sessionId=" + sessionId 835a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown + ", sessionStatus=" + sessionStatus); 836a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 837a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 838a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown if (mStatusCallback != null) { 839a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown mStatusCallback.onSessionStatusChanged(intent.getExtras(), 840a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown sessionId, sessionStatus); 841a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 842a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 843a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 844a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 845a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 846a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 847a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * A callback that will receive media status updates. 848a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 849a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static abstract class StatusCallback { 850a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 851a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when the status of a media item changes. 852a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 853a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param data The result data bundle. 854a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The session id. 855a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionStatus The session status, or null if unknown. 856a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemId The item id. 857a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemStatus The item status. 858a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 859a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onItemStatusChanged(Bundle data, 860a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String sessionId, MediaSessionStatus sessionStatus, 861a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String itemId, MediaItemStatus itemStatus) { 862a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 863a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 864a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 865a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when the status of a media session changes. 866a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 867a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param data The result data bundle. 868a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The session id. 869a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionStatus The session status, or null if unknown. 870a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 871a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onSessionStatusChanged(Bundle data, 872a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String sessionId, MediaSessionStatus sessionStatus) { 873a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 874a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 875a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 876a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when the session of the remote playback client changes. 877a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 878a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The new session id. 879a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 880a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onSessionChanged(String sessionId) { 881a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 882a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 883a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 884a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 885a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Base callback type for remote playback requests. 886a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 887a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static abstract class ActionCallback { 888a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 889a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when a media control request fails. 890a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 891a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param error A localized error message which may be shown to the user, or null 892a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * if the cause of the error is unclear. 893a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param code The error code, or {@link MediaControlIntent#ERROR_UNKNOWN} if unknown. 894a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param data The error data bundle, or null if none. 895a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 896a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onError(String error, int code, Bundle data) { 897a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 898a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 899a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 900a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 901a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Callback for remote playback requests that operate on items. 902a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 903a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static abstract class ItemActionCallback extends ActionCallback { 904a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 905a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when the request succeeds. 906a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 907a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param data The result data bundle. 908a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The session id. 909a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionStatus The session status, or null if unknown. 910a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemId The item id. 911a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param itemStatus The item status. 912a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 913a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onResult(Bundle data, String sessionId, MediaSessionStatus sessionStatus, 914a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown String itemId, MediaItemStatus itemStatus) { 915a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 916a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 917a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown 918a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 919a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Callback for remote playback requests that operate on sessions. 920a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 921a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public static abstract class SessionActionCallback extends ActionCallback { 922a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown /** 923a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * Called when the request succeeds. 924a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * 925a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param data The result data bundle. 926a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionId The session id. 927a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown * @param sessionStatus The session status, or null if unknown. 928a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown */ 929a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown public void onResult(Bundle data, String sessionId, MediaSessionStatus sessionStatus) { 930a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 931a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown } 932a97f1edf7624785c41ec0bfec6fd12c2388d9234Jeff Brown} 933