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