SampleMediaRouteProvider.java revision 50070d31a0e0f0173b4bfe3b65a2a62496537c44
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.example.android.supportv7.media; 18 19import android.app.PendingIntent; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.content.IntentFilter.MalformedMimeTypeException; 24import android.content.IntentSender; 25import android.content.res.Resources; 26import android.media.AudioManager; 27import android.media.MediaRouter; 28import android.net.Uri; 29import android.os.Bundle; 30import android.support.v7.media.MediaControlIntent; 31import android.support.v7.media.MediaRouteDescriptor; 32import android.support.v7.media.MediaRouteProvider; 33import android.support.v7.media.MediaRouteProviderDescriptor; 34import android.support.v7.media.MediaRouter.ControlRequestCallback; 35import android.support.v7.media.MediaSessionStatus; 36import android.util.Log; 37 38import com.example.android.supportv7.R; 39 40import java.util.ArrayList; 41 42/** 43 * Demonstrates how to create a custom media route provider. 44 * 45 * @see SampleMediaRouteProviderService 46 */ 47final class SampleMediaRouteProvider extends MediaRouteProvider { 48 private static final String TAG = "SampleMediaRouteProvider"; 49 50 private static final String FIXED_VOLUME_ROUTE_ID = "fixed"; 51 private static final String VARIABLE_VOLUME_BASIC_ROUTE_ID = "variable_basic"; 52 private static final String VARIABLE_VOLUME_QUEUING_ROUTE_ID = "variable_queuing"; 53 private static final String VARIABLE_VOLUME_SESSION_ROUTE_ID = "variable_session"; 54 55 private static final int VOLUME_MAX = 10; 56 57 /** 58 * A custom media control intent category for special requests that are 59 * supported by this provider's routes. 60 */ 61 public static final String CATEGORY_SAMPLE_ROUTE = 62 "com.example.android.supportv7.media.CATEGORY_SAMPLE_ROUTE"; 63 64 /** 65 * A custom media control intent action for special requests that are 66 * supported by this provider's routes. 67 * </p> 68 * 69 * @see #TRACK_INFO_DESC 70 * @see #TRACK_INFO_SNAPSHOT 71 */ 72 public static final String ACTION_GET_TRACK_INFO = 73 "com.example.android.supportv7.media.ACTION_GET_TRACK_INFO"; 74 75 /** 76 * {@link #ACTION_GET_TRACK_INFO} result data: a string of information about 77 * the currently playing media item 78 */ 79 public static final String TRACK_INFO_DESC = 80 "com.example.android.supportv7.media.EXTRA_TRACK_INFO_DESC"; 81 82 /** 83 * {@link #ACTION_GET_TRACK_INFO} result data: a bitmap containing a snapshot 84 * of the currently playing media item 85 */ 86 public static final String TRACK_INFO_SNAPSHOT = 87 "com.example.android.supportv7.media.EXTRA_TRACK_INFO_SNAPSHOT"; 88 89 private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; 90 private static final ArrayList<IntentFilter> CONTROL_FILTERS_QUEUING; 91 private static final ArrayList<IntentFilter> CONTROL_FILTERS_SESSION; 92 93 static { 94 IntentFilter f1 = new IntentFilter(); 95 f1.addCategory(CATEGORY_SAMPLE_ROUTE); 96 f1.addAction(ACTION_GET_TRACK_INFO); 97 98 IntentFilter f2 = new IntentFilter(); 99 f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 100 f2.addAction(MediaControlIntent.ACTION_PLAY); 101 f2.addDataScheme("http"); 102 f2.addDataScheme("https"); 103 f2.addDataScheme("rtsp"); 104 f2.addDataScheme("file"); 105 addDataTypeUnchecked(f2, "video/*"); 106 107 IntentFilter f3 = new IntentFilter(); 108 f3.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 109 f3.addAction(MediaControlIntent.ACTION_SEEK); 110 f3.addAction(MediaControlIntent.ACTION_GET_STATUS); 111 f3.addAction(MediaControlIntent.ACTION_PAUSE); 112 f3.addAction(MediaControlIntent.ACTION_RESUME); 113 f3.addAction(MediaControlIntent.ACTION_STOP); 114 115 IntentFilter f4 = new IntentFilter(); 116 f4.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 117 f4.addAction(MediaControlIntent.ACTION_ENQUEUE); 118 f4.addDataScheme("http"); 119 f4.addDataScheme("https"); 120 f4.addDataScheme("rtsp"); 121 f4.addDataScheme("file"); 122 addDataTypeUnchecked(f4, "video/*"); 123 124 IntentFilter f5 = new IntentFilter(); 125 f5.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 126 f5.addAction(MediaControlIntent.ACTION_REMOVE); 127 128 IntentFilter f6 = new IntentFilter(); 129 f6.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); 130 f6.addAction(MediaControlIntent.ACTION_START_SESSION); 131 f6.addAction(MediaControlIntent.ACTION_GET_SESSION_STATUS); 132 f6.addAction(MediaControlIntent.ACTION_END_SESSION); 133 134 CONTROL_FILTERS_BASIC = new ArrayList<>(); 135 CONTROL_FILTERS_BASIC.add(f1); 136 CONTROL_FILTERS_BASIC.add(f2); 137 CONTROL_FILTERS_BASIC.add(f3); 138 139 CONTROL_FILTERS_QUEUING = new ArrayList<>(CONTROL_FILTERS_BASIC); 140 CONTROL_FILTERS_QUEUING.add(f4); 141 CONTROL_FILTERS_QUEUING.add(f5); 142 143 CONTROL_FILTERS_SESSION = new ArrayList<>(CONTROL_FILTERS_QUEUING); 144 CONTROL_FILTERS_SESSION.add(f6); 145 } 146 147 private static void addDataTypeUnchecked(IntentFilter filter, String type) { 148 try { 149 filter.addDataType(type); 150 } catch (MalformedMimeTypeException ex) { 151 throw new RuntimeException(ex); 152 } 153 } 154 155 private int mVolume = 5; 156 157 public SampleMediaRouteProvider(Context context) { 158 super(context); 159 160 publishRoutes(); 161 } 162 163 @Override 164 public RouteController onCreateRouteController(String routeId) { 165 return new SampleRouteController(routeId); 166 } 167 168 private void publishRoutes() { 169 Resources r = getContext().getResources(); 170 Intent settingsIntent = new Intent(Intent.ACTION_MAIN); 171 settingsIntent.setClass(getContext(), SampleMediaRouteSettingsActivity.class); 172 IntentSender is = PendingIntent.getActivity(getContext(), 99, settingsIntent, 173 Intent.FLAG_ACTIVITY_NEW_TASK).getIntentSender(); 174 175 MediaRouteDescriptor routeDescriptor1 = new MediaRouteDescriptor.Builder( 176 FIXED_VOLUME_ROUTE_ID, 177 r.getString(R.string.fixed_volume_route_name)) 178 .setDescription(r.getString(R.string.sample_route_description)) 179 .addControlFilters(CONTROL_FILTERS_BASIC) 180 .setPlaybackStream(AudioManager.STREAM_MUSIC) 181 .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) 182 .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED) 183 .setVolume(VOLUME_MAX) 184 .setCanDisconnect(true) 185 .setSettingsActivity(is) 186 .build(); 187 188 MediaRouteDescriptor routeDescriptor2 = new MediaRouteDescriptor.Builder( 189 VARIABLE_VOLUME_BASIC_ROUTE_ID, 190 r.getString(R.string.variable_volume_basic_route_name)) 191 .setDescription(r.getString(R.string.sample_route_description)) 192 .addControlFilters(CONTROL_FILTERS_BASIC) 193 .setPlaybackStream(AudioManager.STREAM_MUSIC) 194 .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) 195 .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) 196 .setVolumeMax(VOLUME_MAX) 197 .setVolume(mVolume) 198 .setSettingsActivity(is) 199 .build(); 200 201 MediaRouteDescriptor routeDescriptor3 = new MediaRouteDescriptor.Builder( 202 VARIABLE_VOLUME_QUEUING_ROUTE_ID, 203 r.getString(R.string.variable_volume_queuing_route_name)) 204 .setDescription(r.getString(R.string.sample_route_description)) 205 .addControlFilters(CONTROL_FILTERS_QUEUING) 206 .setPlaybackStream(AudioManager.STREAM_MUSIC) 207 .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) 208 .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) 209 .setVolumeMax(VOLUME_MAX) 210 .setVolume(mVolume) 211 .setCanDisconnect(true) 212 .build(); 213 214 MediaRouteDescriptor routeDescriptor4 = new MediaRouteDescriptor.Builder( 215 VARIABLE_VOLUME_SESSION_ROUTE_ID, 216 r.getString(R.string.variable_volume_session_route_name)) 217 .setDescription(r.getString(R.string.sample_route_description)) 218 .addControlFilters(CONTROL_FILTERS_SESSION) 219 .setPlaybackStream(AudioManager.STREAM_MUSIC) 220 .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) 221 .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) 222 .setVolumeMax(VOLUME_MAX) 223 .setVolume(mVolume) 224 .build(); 225 226 MediaRouteProviderDescriptor providerDescriptor = new MediaRouteProviderDescriptor.Builder() 227 .addRoute(routeDescriptor1) 228 .addRoute(routeDescriptor2) 229 .addRoute(routeDescriptor3) 230 .addRoute(routeDescriptor4) 231 .build(); 232 setDescriptor(providerDescriptor); 233 } 234 235 private final class SampleRouteController extends MediaRouteProvider.RouteController { 236 private final String mRouteId; 237 private final SessionManager mSessionManager = new SessionManager("mrp"); 238 private final Player mPlayer; 239 private PendingIntent mSessionReceiver; 240 241 public SampleRouteController(String routeId) { 242 mRouteId = routeId; 243 mPlayer = Player.create(getContext(), null, null); 244 mSessionManager.setPlayer(mPlayer); 245 mSessionManager.setCallback(new SessionManager.Callback() { 246 @Override 247 public void onStatusChanged() { 248 } 249 250 @Override 251 public void onItemChanged(PlaylistItem item) { 252 handleStatusChange(item); 253 } 254 }); 255 setVolumeInternal(mVolume); 256 Log.d(TAG, mRouteId + ": Controller created"); 257 } 258 259 @Override 260 public void onRelease() { 261 Log.d(TAG, mRouteId + ": Controller released"); 262 mPlayer.release(); 263 } 264 265 @Override 266 public void onSelect() { 267 Log.d(TAG, mRouteId + ": Selected"); 268 mPlayer.connect(null); 269 } 270 271 @Override 272 public void onUnselect() { 273 Log.d(TAG, mRouteId + ": Unselected"); 274 mPlayer.release(); 275 } 276 277 @Override 278 public void onSetVolume(int volume) { 279 Log.d(TAG, mRouteId + ": Set volume to " + volume); 280 if (!mRouteId.equals(FIXED_VOLUME_ROUTE_ID)) { 281 setVolumeInternal(volume); 282 } 283 } 284 285 @Override 286 public void onUpdateVolume(int delta) { 287 Log.d(TAG, mRouteId + ": Update volume by " + delta); 288 if (!mRouteId.equals(FIXED_VOLUME_ROUTE_ID)) { 289 setVolumeInternal(mVolume + delta); 290 } 291 } 292 293 @Override 294 public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { 295 Log.d(TAG, mRouteId + ": Received control request " + intent); 296 String action = intent.getAction(); 297 if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { 298 boolean success = false; 299 if (action.equals(MediaControlIntent.ACTION_PLAY)) { 300 success = handlePlay(intent, callback); 301 } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) { 302 success = handleEnqueue(intent, callback); 303 } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) { 304 success = handleRemove(intent, callback); 305 } else if (action.equals(MediaControlIntent.ACTION_SEEK)) { 306 success = handleSeek(intent, callback); 307 } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) { 308 success = handleGetStatus(intent, callback); 309 } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) { 310 success = handlePause(intent, callback); 311 } else if (action.equals(MediaControlIntent.ACTION_RESUME)) { 312 success = handleResume(intent, callback); 313 } else if (action.equals(MediaControlIntent.ACTION_STOP)) { 314 success = handleStop(intent, callback); 315 } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) { 316 success = handleStartSession(intent, callback); 317 } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) { 318 success = handleGetSessionStatus(intent, callback); 319 } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) { 320 success = handleEndSession(intent, callback); 321 } 322 Log.d(TAG, mSessionManager.toString()); 323 return success; 324 } 325 326 if (action.equals(ACTION_GET_TRACK_INFO) 327 && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) { 328 Bundle data = new Bundle(); 329 PlaylistItem item = mSessionManager.getCurrentItem(); 330 if (item != null) { 331 data.putString(TRACK_INFO_DESC, item.toString()); 332 data.putParcelable(TRACK_INFO_SNAPSHOT, mPlayer.getSnapshot()); 333 } 334 if (callback != null) { 335 callback.onResult(data); 336 } 337 return true; 338 } 339 return false; 340 } 341 342 private void setVolumeInternal(int volume) { 343 if (volume >= 0 && volume <= VOLUME_MAX) { 344 mVolume = volume; 345 Log.d(TAG, mRouteId + ": New volume is " + mVolume); 346 AudioManager audioManager = 347 (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE); 348 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); 349 publishRoutes(); 350 } 351 } 352 353 private boolean handlePlay(Intent intent, ControlRequestCallback callback) { 354 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 355 if (sid != null && !sid.equals(mSessionManager.getSessionId())) { 356 Log.d(TAG, "handlePlay fails because of bad sid="+sid); 357 return false; 358 } 359 if (mSessionManager.hasSession()) { 360 mSessionManager.stop(); 361 } 362 return handleEnqueue(intent, callback); 363 } 364 365 private boolean handleEnqueue(Intent intent, ControlRequestCallback callback) { 366 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 367 if (sid != null && !sid.equals(mSessionManager.getSessionId())) { 368 Log.d(TAG, "handleEnqueue fails because of bad sid="+sid); 369 return false; 370 } 371 372 Uri uri = intent.getData(); 373 if (uri == null) { 374 Log.d(TAG, "handleEnqueue fails because of bad uri="+uri); 375 return false; 376 } 377 378 boolean enqueue = intent.getAction().equals(MediaControlIntent.ACTION_ENQUEUE); 379 String mime = intent.getType(); 380 long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0); 381 Bundle metadata = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_METADATA); 382 Bundle headers = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_HTTP_HEADERS); 383 PendingIntent receiver = (PendingIntent)intent.getParcelableExtra( 384 MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER); 385 386 Log.d(TAG, mRouteId + ": Received " + (enqueue?"enqueue":"play") + " request" 387 + ", uri=" + uri 388 + ", mime=" + mime 389 + ", sid=" + sid 390 + ", pos=" + pos 391 + ", metadata=" + metadata 392 + ", headers=" + headers 393 + ", receiver=" + receiver); 394 PlaylistItem item = mSessionManager.add(uri, mime, receiver); 395 if (callback != null) { 396 if (item != null) { 397 Bundle result = new Bundle(); 398 result.putString(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId()); 399 result.putString(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId()); 400 result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS, 401 item.getStatus().asBundle()); 402 callback.onResult(result); 403 } else { 404 callback.onError("Failed to open " + uri.toString(), null); 405 } 406 } 407 return true; 408 } 409 410 private boolean handleRemove(Intent intent, ControlRequestCallback callback) { 411 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 412 if (sid == null || !sid.equals(mSessionManager.getSessionId())) { 413 return false; 414 } 415 416 String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); 417 PlaylistItem item = mSessionManager.remove(iid); 418 if (callback != null) { 419 if (item != null) { 420 Bundle result = new Bundle(); 421 result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS, 422 item.getStatus().asBundle()); 423 callback.onResult(result); 424 } else { 425 callback.onError("Failed to remove" + 426 ", sid=" + sid + ", iid=" + iid, null); 427 } 428 } 429 return (item != null); 430 } 431 432 private boolean handleSeek(Intent intent, ControlRequestCallback callback) { 433 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 434 if (sid == null || !sid.equals(mSessionManager.getSessionId())) { 435 return false; 436 } 437 438 String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); 439 long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0); 440 Log.d(TAG, mRouteId + ": Received seek request, pos=" + pos); 441 PlaylistItem item = mSessionManager.seek(iid, pos); 442 if (callback != null) { 443 if (item != null) { 444 Bundle result = new Bundle(); 445 result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS, 446 item.getStatus().asBundle()); 447 callback.onResult(result); 448 } else { 449 callback.onError("Failed to seek" + 450 ", sid=" + sid + ", iid=" + iid + ", pos=" + pos, null); 451 } 452 } 453 return (item != null); 454 } 455 456 private boolean handleGetStatus(Intent intent, ControlRequestCallback callback) { 457 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 458 String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); 459 Log.d(TAG, mRouteId + ": Received getStatus request, sid=" + sid + ", iid=" + iid); 460 PlaylistItem item = mSessionManager.getStatus(iid); 461 if (callback != null) { 462 if (item != null) { 463 Bundle result = new Bundle(); 464 result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS, 465 item.getStatus().asBundle()); 466 callback.onResult(result); 467 } else { 468 callback.onError("Failed to get status" + 469 ", sid=" + sid + ", iid=" + iid, null); 470 } 471 } 472 return (item != null); 473 } 474 475 private boolean handlePause(Intent intent, ControlRequestCallback callback) { 476 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 477 boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId()); 478 mSessionManager.pause(); 479 if (callback != null) { 480 if (success) { 481 callback.onResult(new Bundle()); 482 handleSessionStatusChange(sid); 483 } else { 484 callback.onError("Failed to pause, sid=" + sid, null); 485 } 486 } 487 return success; 488 } 489 490 private boolean handleResume(Intent intent, ControlRequestCallback callback) { 491 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 492 boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId()); 493 mSessionManager.resume(); 494 if (callback != null) { 495 if (success) { 496 callback.onResult(new Bundle()); 497 handleSessionStatusChange(sid); 498 } else { 499 callback.onError("Failed to resume, sid=" + sid, null); 500 } 501 } 502 return success; 503 } 504 505 private boolean handleStop(Intent intent, ControlRequestCallback callback) { 506 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 507 boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId()); 508 mSessionManager.stop(); 509 if (callback != null) { 510 if (success) { 511 callback.onResult(new Bundle()); 512 handleSessionStatusChange(sid); 513 } else { 514 callback.onError("Failed to stop, sid=" + sid, null); 515 } 516 } 517 return success; 518 } 519 520 private boolean handleStartSession(Intent intent, ControlRequestCallback callback) { 521 String sid = mSessionManager.startSession(); 522 Log.d(TAG, "StartSession returns sessionId "+sid); 523 if (callback != null) { 524 if (sid != null) { 525 Bundle result = new Bundle(); 526 result.putString(MediaControlIntent.EXTRA_SESSION_ID, sid); 527 result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS, 528 mSessionManager.getSessionStatus(sid).asBundle()); 529 callback.onResult(result); 530 mSessionReceiver = (PendingIntent)intent.getParcelableExtra( 531 MediaControlIntent.EXTRA_SESSION_STATUS_UPDATE_RECEIVER); 532 handleSessionStatusChange(sid); 533 } else { 534 callback.onError("Failed to start session.", null); 535 } 536 } 537 return (sid != null); 538 } 539 540 private boolean handleGetSessionStatus(Intent intent, ControlRequestCallback callback) { 541 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 542 543 MediaSessionStatus sessionStatus = mSessionManager.getSessionStatus(sid); 544 if (callback != null) { 545 if (sessionStatus != null) { 546 Bundle result = new Bundle(); 547 result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS, 548 mSessionManager.getSessionStatus(sid).asBundle()); 549 callback.onResult(result); 550 } else { 551 callback.onError("Failed to get session status, sid=" + sid, null); 552 } 553 } 554 return (sessionStatus != null); 555 } 556 557 private boolean handleEndSession(Intent intent, ControlRequestCallback callback) { 558 String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); 559 boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId()) 560 && mSessionManager.endSession(); 561 if (callback != null) { 562 if (success) { 563 Bundle result = new Bundle(); 564 MediaSessionStatus sessionStatus = new MediaSessionStatus.Builder( 565 MediaSessionStatus.SESSION_STATE_ENDED).build(); 566 result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS, sessionStatus.asBundle()); 567 callback.onResult(result); 568 handleSessionStatusChange(sid); 569 mSessionReceiver = null; 570 } else { 571 callback.onError("Failed to end session, sid=" + sid, null); 572 } 573 } 574 return success; 575 } 576 577 private void handleStatusChange(PlaylistItem item) { 578 if (item == null) { 579 item = mSessionManager.getCurrentItem(); 580 } 581 if (item != null) { 582 PendingIntent receiver = item.getUpdateReceiver(); 583 if (receiver != null) { 584 Intent intent = new Intent(); 585 intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId()); 586 intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId()); 587 intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS, 588 item.getStatus().asBundle()); 589 try { 590 receiver.send(getContext(), 0, intent); 591 Log.d(TAG, mRouteId + ": Sending status update from provider"); 592 } catch (PendingIntent.CanceledException e) { 593 Log.d(TAG, mRouteId + ": Failed to send status update!"); 594 } 595 } 596 } 597 } 598 599 private void handleSessionStatusChange(String sid) { 600 if (mSessionReceiver != null) { 601 Intent intent = new Intent(); 602 intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sid); 603 intent.putExtra(MediaControlIntent.EXTRA_SESSION_STATUS, 604 mSessionManager.getSessionStatus(sid).asBundle()); 605 try { 606 mSessionReceiver.send(getContext(), 0, intent); 607 Log.d(TAG, mRouteId + ": Sending session status update from provider"); 608 } catch (PendingIntent.CanceledException e) { 609 Log.d(TAG, mRouteId + ": Failed to send session status update!"); 610 } 611 } 612 } 613 } 614} 615