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