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.ComponentName; 21import android.content.Context; 22import android.content.DialogInterface; 23import android.content.Intent; 24import android.media.AudioManager; 25import android.media.AudioManager.OnAudioFocusChangeListener; 26import android.net.Uri; 27import android.os.Bundle; 28import android.os.Environment; 29import android.os.Handler; 30import android.os.SystemClock; 31import android.support.v4.media.session.MediaSessionCompat; 32import android.support.v4.view.MenuItemCompat; 33import android.support.v7.app.AppCompatActivity; 34import android.support.v7.app.MediaRouteActionProvider; 35import android.support.v7.app.MediaRouteControllerDialog; 36import android.support.v7.app.MediaRouteControllerDialogFragment; 37import android.support.v7.app.MediaRouteDialogFactory; 38import android.support.v7.media.MediaControlIntent; 39import android.support.v7.media.MediaItemStatus; 40import android.support.v7.media.MediaRouteSelector; 41import android.support.v7.media.MediaRouter; 42import android.support.v7.media.MediaRouter.ProviderInfo; 43import android.support.v7.media.MediaRouter.RouteInfo; 44import android.util.Log; 45import android.view.KeyEvent; 46import android.view.Menu; 47import android.view.MenuItem; 48import android.view.View; 49import android.view.View.OnClickListener; 50import android.view.ViewGroup; 51import android.widget.AdapterView; 52import android.widget.AdapterView.OnItemClickListener; 53import android.widget.ArrayAdapter; 54import android.widget.CheckBox; 55import android.widget.ImageButton; 56import android.widget.ListView; 57import android.widget.SeekBar; 58import android.widget.SeekBar.OnSeekBarChangeListener; 59import android.widget.TabHost; 60import android.widget.TabHost.OnTabChangeListener; 61import android.widget.TabHost.TabSpec; 62import android.widget.TextView; 63 64import com.example.android.supportv7.R; 65 66import java.io.File; 67 68/** 69 * <h3>Media Router Support Activity</h3> 70 * 71 * <p> 72 * This demonstrates how to use the {@link MediaRouter} API to build an 73 * application that allows the user to send content to various rendering 74 * targets. 75 * </p> 76 */ 77public class SampleMediaRouterActivity extends AppCompatActivity { 78 private static final String TAG = "SampleMediaRouterActivity"; 79 private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment"; 80 private static final boolean ENABLE_DEFAULT_CONTROL_CHECK_BOX = false; 81 82 private MediaRouter mMediaRouter; 83 private MediaRouteSelector mSelector; 84 private LibraryAdapter mLibraryItems; 85 private PlaylistAdapter mPlayListItems; 86 private TextView mInfoTextView; 87 private ListView mLibraryView; 88 private ListView mPlayListView; 89 private CheckBox mUseDefaultControlCheckBox; 90 private ImageButton mPauseResumeButton; 91 private ImageButton mStopButton; 92 private SeekBar mSeekBar; 93 private boolean mNeedResume; 94 private boolean mSeeking; 95 96 private final Handler mHandler = new Handler(); 97 private final Runnable mUpdateSeekRunnable = new Runnable() { 98 @Override 99 public void run() { 100 updateProgress(); 101 // update Ui every 1 second 102 mHandler.postDelayed(this, 1000); 103 } 104 }; 105 106 private final SessionManager mSessionManager = new SessionManager("app"); 107 private Player mPlayer; 108 109 private final MediaRouter.Callback mMediaRouterCB = new MediaRouter.Callback() { 110 // Return a custom callback that will simply log all of the route events 111 // for demonstration purposes. 112 @Override 113 public void onRouteAdded(MediaRouter router, RouteInfo route) { 114 Log.d(TAG, "onRouteAdded: route=" + route); 115 } 116 117 @Override 118 public void onRouteChanged(MediaRouter router, RouteInfo route) { 119 Log.d(TAG, "onRouteChanged: route=" + route); 120 } 121 122 @Override 123 public void onRouteRemoved(MediaRouter router, RouteInfo route) { 124 Log.d(TAG, "onRouteRemoved: route=" + route); 125 } 126 127 @Override 128 public void onRouteSelected(MediaRouter router, RouteInfo route) { 129 Log.d(TAG, "onRouteSelected: route=" + route); 130 131 mPlayer = Player.create(SampleMediaRouterActivity.this, route, mMediaSession); 132 mPlayer.updatePresentation(); 133 mSessionManager.setPlayer(mPlayer); 134 mSessionManager.unsuspend(); 135 136 updateUi(); 137 } 138 139 @Override 140 public void onRouteUnselected(MediaRouter router, RouteInfo route) { 141 Log.d(TAG, "onRouteUnselected: route=" + route); 142 mMediaSession.setActive(false); 143 144 PlaylistItem item = getCheckedPlaylistItem(); 145 if (item != null) { 146 long pos = item.getPosition() + (mSessionManager.isPaused() ? 147 0 : (SystemClock.elapsedRealtime() - item.getTimestamp())); 148 mSessionManager.suspend(pos); 149 } 150 mPlayer.updatePresentation(); 151 mPlayer.release(); 152 } 153 154 @Override 155 public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) { 156 Log.d(TAG, "onRouteVolumeChanged: route=" + route); 157 } 158 159 @Override 160 public void onRoutePresentationDisplayChanged( 161 MediaRouter router, RouteInfo route) { 162 Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route); 163 mPlayer.updatePresentation(); 164 } 165 166 @Override 167 public void onProviderAdded(MediaRouter router, ProviderInfo provider) { 168 Log.d(TAG, "onRouteProviderAdded: provider=" + provider); 169 } 170 171 @Override 172 public void onProviderRemoved(MediaRouter router, ProviderInfo provider) { 173 Log.d(TAG, "onRouteProviderRemoved: provider=" + provider); 174 } 175 176 @Override 177 public void onProviderChanged(MediaRouter router, ProviderInfo provider) { 178 Log.d(TAG, "onRouteProviderChanged: provider=" + provider); 179 } 180 }; 181 182 private MediaSessionCompat mMediaSession; 183 private ComponentName mEventReceiver; 184 private AudioManager mAudioManager; 185 private PendingIntent mMediaPendingIntent; 186 private final OnAudioFocusChangeListener mAfChangeListener = 187 new OnAudioFocusChangeListener() { 188 @Override 189 public void onAudioFocusChange(int focusChange) { 190 if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 191 Log.d(TAG, "onAudioFocusChange: LOSS_TRANSIENT"); 192 } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 193 Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_GAIN"); 194 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 195 Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_LOSS"); 196 } 197 } 198 }; 199 200 @Override 201 protected void onCreate(Bundle savedInstanceState) { 202 // Be sure to call the super class. 203 super.onCreate(savedInstanceState); 204 205 // Get the media router service. 206 mMediaRouter = MediaRouter.getInstance(this); 207 208 // Create a route selector for the type of routes that we care about. 209 mSelector = new MediaRouteSelector.Builder() 210 .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO) 211 .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO) 212 .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) 213 .addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE) 214 .build(); 215 mMediaRouter.addCallback(mSelector, mMediaRouterCB); 216 217 // Populate an array adapter with streaming media items. 218 String[] mediaNames = getResources().getStringArray(R.array.media_names); 219 String[] mediaUris = getResources().getStringArray(R.array.media_uris); 220 mLibraryItems = new LibraryAdapter(); 221 for (int i = 0; i < mediaNames.length; i++) { 222 mLibraryItems.add(new MediaItem( 223 "[streaming] "+mediaNames[i], Uri.parse(mediaUris[i]), "video/mp4")); 224 } 225 226 // Scan local external storage directory for media files. 227 File externalDir = Environment.getExternalStorageDirectory(); 228 if (externalDir != null) { 229 File list[] = externalDir.listFiles(); 230 if (list != null) { 231 for (int i = 0; i < list.length; i++) { 232 String filename = list[i].getName(); 233 if (filename.matches(".*\\.(m4v|mp4)")) { 234 mLibraryItems.add(new MediaItem("[local] " + filename, 235 Uri.fromFile(list[i]), "video/mp4")); 236 } 237 } 238 } 239 } 240 241 mPlayListItems = new PlaylistAdapter(); 242 243 // Initialize the layout. 244 setContentView(R.layout.sample_media_router); 245 246 TabHost tabHost=(TabHost)findViewById(R.id.tabHost); 247 tabHost.setup(); 248 String tabName = getResources().getString(R.string.library_tab_text); 249 TabSpec spec1=tabHost.newTabSpec(tabName); 250 spec1.setContent(R.id.tab1); 251 spec1.setIndicator(tabName); 252 253 tabName = getResources().getString(R.string.playlist_tab_text); 254 TabSpec spec2=tabHost.newTabSpec(tabName); 255 spec2.setIndicator(tabName); 256 spec2.setContent(R.id.tab2); 257 258 tabName = getResources().getString(R.string.info_tab_text); 259 TabSpec spec3=tabHost.newTabSpec(tabName); 260 spec3.setIndicator(tabName); 261 spec3.setContent(R.id.tab3); 262 263 tabHost.addTab(spec1); 264 tabHost.addTab(spec2); 265 tabHost.addTab(spec3); 266 tabHost.setOnTabChangedListener(new OnTabChangeListener() { 267 @Override 268 public void onTabChanged(String arg0) { 269 updateUi(); 270 } 271 }); 272 273 mLibraryView = (ListView) findViewById(R.id.media); 274 mLibraryView.setAdapter(mLibraryItems); 275 mLibraryView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 276 mLibraryView.setOnItemClickListener(new OnItemClickListener() { 277 @Override 278 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 279 updateButtons(); 280 } 281 }); 282 283 mPlayListView = (ListView) findViewById(R.id.playlist); 284 mPlayListView.setAdapter(mPlayListItems); 285 mPlayListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 286 mPlayListView.setOnItemClickListener(new OnItemClickListener() { 287 @Override 288 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 289 updateButtons(); 290 } 291 }); 292 293 mInfoTextView = (TextView) findViewById(R.id.info); 294 295 mUseDefaultControlCheckBox = (CheckBox) findViewById(R.id.custom_control_view_checkbox); 296 if (ENABLE_DEFAULT_CONTROL_CHECK_BOX) { 297 mUseDefaultControlCheckBox.setVisibility(View.VISIBLE); 298 } 299 mPauseResumeButton = (ImageButton)findViewById(R.id.pause_resume_button); 300 mPauseResumeButton.setOnClickListener(new OnClickListener() { 301 @Override 302 public void onClick(View v) { 303 if (mSessionManager.isPaused()) { 304 mSessionManager.resume(); 305 } else { 306 mSessionManager.pause(); 307 } 308 } 309 }); 310 311 mStopButton = (ImageButton)findViewById(R.id.stop_button); 312 mStopButton.setOnClickListener(new OnClickListener() { 313 @Override 314 public void onClick(View v) { 315 mSessionManager.stop(); 316 } 317 }); 318 319 mSeekBar = (SeekBar) findViewById(R.id.seekbar); 320 mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 321 @Override 322 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 323 PlaylistItem item = getCheckedPlaylistItem(); 324 if (fromUser && item != null && item.getDuration() > 0) { 325 long pos = progress * item.getDuration() / 100; 326 mSessionManager.seek(item.getItemId(), pos); 327 item.setPosition(pos); 328 item.setTimestamp(SystemClock.elapsedRealtime()); 329 } 330 } 331 @Override 332 public void onStartTrackingTouch(SeekBar seekBar) { 333 mSeeking = true; 334 } 335 @Override 336 public void onStopTrackingTouch(SeekBar seekBar) { 337 mSeeking = false; 338 updateUi(); 339 } 340 }); 341 342 // Schedule Ui update 343 mHandler.postDelayed(mUpdateSeekRunnable, 1000); 344 345 // Build the PendingIntent for the remote control client 346 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 347 mEventReceiver = new ComponentName(getPackageName(), 348 SampleMediaButtonReceiver.class.getName()); 349 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 350 mediaButtonIntent.setComponent(mEventReceiver); 351 mMediaPendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0); 352 353 // Create and register the remote control client 354 createMediaSession(); 355 mMediaRouter.setMediaSessionCompat(mMediaSession); 356 357 // Set up playback manager and player 358 mPlayer = Player.create(SampleMediaRouterActivity.this, 359 mMediaRouter.getSelectedRoute(), mMediaSession); 360 361 mSessionManager.setPlayer(mPlayer); 362 mSessionManager.setCallback(new SessionManager.Callback() { 363 @Override 364 public void onStatusChanged() { 365 updateUi(); 366 } 367 368 @Override 369 public void onItemChanged(PlaylistItem item) { 370 } 371 }); 372 373 updateUi(); 374 } 375 376 private void createMediaSession() { 377 // Create the MediaSession 378 mMediaSession = new MediaSessionCompat(this, "SampleMediaRouter", mEventReceiver, 379 mMediaPendingIntent); 380 mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS 381 | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); 382 mMediaSession.setCallback(new MediaSessionCompat.Callback() { 383 @Override 384 public boolean onMediaButtonEvent(Intent mediaButtonEvent) { 385 if (mediaButtonEvent != null) { 386 return handleMediaKey( 387 (KeyEvent) mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)); 388 } 389 return super.onMediaButtonEvent(mediaButtonEvent); 390 } 391 392 @Override 393 public void onPlay() { 394 mSessionManager.resume(); 395 } 396 397 @Override 398 public void onPause() { 399 mSessionManager.pause(); 400 } 401 }); 402 403 SampleMediaButtonReceiver.setActivity(SampleMediaRouterActivity.this); 404 } 405 406 public boolean handleMediaKey(KeyEvent event) { 407 if (event != null && event.getAction() == KeyEvent.ACTION_DOWN 408 && event.getRepeatCount() == 0) { 409 switch (event.getKeyCode()) { 410 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 411 case KeyEvent.KEYCODE_HEADSETHOOK: 412 { 413 Log.d(TAG, "Received Play/Pause event from RemoteControlClient"); 414 if (mSessionManager.isPaused()) { 415 mSessionManager.resume(); 416 } else { 417 mSessionManager.pause(); 418 } 419 return true; 420 } 421 case KeyEvent.KEYCODE_MEDIA_PLAY: 422 { 423 Log.d(TAG, "Received Play event from RemoteControlClient"); 424 if (mSessionManager.isPaused()) { 425 mSessionManager.resume(); 426 } 427 return true; 428 } 429 case KeyEvent.KEYCODE_MEDIA_PAUSE: 430 { 431 Log.d(TAG, "Received Pause event from RemoteControlClient"); 432 if (!mSessionManager.isPaused()) { 433 mSessionManager.pause(); 434 } 435 return true; 436 } 437 case KeyEvent.KEYCODE_MEDIA_STOP: 438 { 439 Log.d(TAG, "Received Stop event from RemoteControlClient"); 440 mSessionManager.stop(); 441 return true; 442 } 443 default: 444 break; 445 } 446 } 447 return false; 448 } 449 450 @Override 451 public boolean onKeyDown(int keyCode, KeyEvent event) { 452 return handleMediaKey(event) || super.onKeyDown(keyCode, event); 453 } 454 455 @Override 456 public boolean onKeyUp(int keyCode, KeyEvent event) { 457 return handleMediaKey(event) || super.onKeyUp(keyCode, event); 458 } 459 460 @Override 461 public void onStart() { 462 // Be sure to call the super class. 463 super.onStart(); 464 } 465 466 @Override 467 public void onPause() { 468 // pause media player for local playback case only 469 if (!mPlayer.isRemotePlayback() && !mSessionManager.isPaused()) { 470 mNeedResume = true; 471 mSessionManager.pause(); 472 } 473 super.onPause(); 474 } 475 476 @Override 477 public void onResume() { 478 // resume media player for local playback case only 479 if (!mPlayer.isRemotePlayback() && mNeedResume) { 480 mSessionManager.resume(); 481 mNeedResume = false; 482 } 483 super.onResume(); 484 } 485 486 @Override 487 public void onDestroy() { 488 mSessionManager.stop(); 489 mPlayer.release(); 490 mMediaSession.release(); 491 super.onDestroy(); 492 } 493 494 @Override 495 public boolean onCreateOptionsMenu(Menu menu) { 496 // Be sure to call the super class. 497 super.onCreateOptionsMenu(menu); 498 499 // Inflate the menu and configure the media router action provider. 500 getMenuInflater().inflate(R.menu.sample_media_router_menu, menu); 501 502 MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); 503 MyMediaRouteActionProvider mediaRouteActionProvider = 504 (MyMediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem); 505 mediaRouteActionProvider.setRouteSelector(mSelector); 506 mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() { 507 @Override 508 public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() { 509 return new ControllerDialogFragment(mPlayer, mUseDefaultControlCheckBox); 510 } 511 }); 512 513 // Return true to show the menu. 514 return true; 515 } 516 517 private void updateProgress() { 518 // Estimate content position from last status time and elapsed time. 519 // (Note this might be slightly out of sync with remote side, however 520 // it avoids frequent polling the MRP.) 521 int progress = 0; 522 PlaylistItem item = getCheckedPlaylistItem(); 523 if (item != null) { 524 int state = item.getState(); 525 long duration = item.getDuration(); 526 if (duration <= 0) { 527 if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING 528 || state == MediaItemStatus.PLAYBACK_STATE_PAUSED) { 529 mSessionManager.updateStatus(); 530 } 531 } else { 532 long position = item.getPosition(); 533 long timeDelta = mSessionManager.isPaused() ? 0 : 534 (SystemClock.elapsedRealtime() - item.getTimestamp()); 535 progress = (int)(100.0 * (position + timeDelta) / duration); 536 } 537 } 538 mSeekBar.setProgress(progress); 539 } 540 541 private void updateUi() { 542 updatePlaylist(); 543 updateRouteDescription(); 544 updateButtons(); 545 if (mPlayer != null && mSessionManager != null) { 546 PlaylistItem currentItem = mSessionManager.getCurrentItem(); 547 if (currentItem != null) { 548 mPlayer.updateMetadata(currentItem); 549 int currentItemState = Player.STATE_IDLE; 550 switch(currentItem.getState()) { 551 case MediaItemStatus.PLAYBACK_STATE_PLAYING: 552 currentItemState = Player.STATE_PLAYING; 553 break; 554 case MediaItemStatus.PLAYBACK_STATE_PAUSED: 555 currentItemState = Player.STATE_PAUSED; 556 break; 557 case MediaItemStatus.PLAYBACK_STATE_PENDING: 558 case MediaItemStatus.PLAYBACK_STATE_BUFFERING: 559 currentItemState = Player.STATE_PREPARING_FOR_PLAY; 560 break; 561 } 562 mPlayer.publishState(currentItemState); 563 } 564 } 565 } 566 567 private void updatePlaylist() { 568 mPlayListItems.clear(); 569 for (PlaylistItem item : mSessionManager.getPlaylist()) { 570 mPlayListItems.add(item); 571 } 572 mPlayListView.invalidate(); 573 } 574 575 private void updateRouteDescription() { 576 RouteInfo route = mMediaRouter.getSelectedRoute(); 577 mInfoTextView.setText("Currently selected route:" 578 + "\nName: " + route.getName() 579 + "\nProvider: " + route.getProvider().getPackageName()); 580 } 581 582 private void updateButtons() { 583 MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(); 584 // show pause or resume icon depending on current state 585 mPauseResumeButton.setImageResource(mSessionManager.isPaused() ? 586 R.drawable.ic_media_play : R.drawable.ic_media_pause); 587 // only enable seek bar when duration is known 588 PlaylistItem item = getCheckedPlaylistItem(); 589 mSeekBar.setEnabled(item != null && item.getDuration() > 0); 590 } 591 592 private PlaylistItem getCheckedPlaylistItem() { 593 int count = mPlayListView.getCount(); 594 int index = mPlayListView.getCheckedItemPosition(); 595 if (count > 0) { 596 if (index < 0 || index >= count) { 597 index = 0; 598 mPlayListView.setItemChecked(0, true); 599 } 600 return mPlayListItems.getItem(index); 601 } 602 return null; 603 } 604 605 private static final class MediaItem { 606 public final String mName; 607 public final Uri mUri; 608 public final String mMime; 609 610 public MediaItem(String name, Uri uri, String mime) { 611 mName = name; 612 mUri = uri; 613 mMime = mime; 614 } 615 616 @Override 617 public String toString() { 618 return mName; 619 } 620 } 621 622 private final class LibraryAdapter extends ArrayAdapter<MediaItem> { 623 public LibraryAdapter() { 624 super(SampleMediaRouterActivity.this, R.layout.media_item); 625 } 626 627 @Override 628 public View getView(int position, View convertView, ViewGroup parent) { 629 final View v; 630 if (convertView == null) { 631 v = getLayoutInflater().inflate(R.layout.media_item, null); 632 } else { 633 v = convertView; 634 } 635 636 final MediaItem item = getItem(position); 637 638 TextView tv = (TextView)v.findViewById(R.id.item_text); 639 tv.setText(item.mName); 640 641 ImageButton b = (ImageButton)v.findViewById(R.id.item_action); 642 b.setImageResource(R.drawable.ic_menu_add); 643 b.setTag(item); 644 b.setOnClickListener(new OnClickListener() { 645 @Override 646 public void onClick(View v) { 647 if (item != null) { 648 mSessionManager.add(item.mName, item.mUri, item.mMime); 649 } 650 } 651 }); 652 653 return v; 654 } 655 } 656 657 private final class PlaylistAdapter extends ArrayAdapter<PlaylistItem> { 658 public PlaylistAdapter() { 659 super(SampleMediaRouterActivity.this, R.layout.media_item); 660 } 661 662 @Override 663 public View getView(int position, View convertView, ViewGroup parent) { 664 final View v; 665 if (convertView == null) { 666 v = getLayoutInflater().inflate(R.layout.media_item, null); 667 } else { 668 v = convertView; 669 } 670 671 final PlaylistItem item = getItem(position); 672 673 TextView tv = (TextView)v.findViewById(R.id.item_text); 674 tv.setText(item.toString()); 675 676 ImageButton b = (ImageButton)v.findViewById(R.id.item_action); 677 b.setImageResource(R.drawable.ic_menu_delete); 678 b.setTag(item); 679 b.setOnClickListener(new OnClickListener() { 680 @Override 681 public void onClick(View v) { 682 if (item != null) { 683 mSessionManager.remove(item.getItemId()); 684 } 685 } 686 }); 687 688 return v; 689 } 690 } 691 692 /** 693 * Trivial subclass of this activity used to provide another copy of the 694 * same activity using a light theme instead of the dark theme. 695 */ 696 public static class Light extends SampleMediaRouterActivity { 697 } 698 699 /** 700 * Trivial subclass of this activity used to provide another copy of the 701 * same activity using a light theme with dark action bar instead of the dark theme. 702 */ 703 public static class LightWithDarkActionBar extends SampleMediaRouterActivity { 704 } 705 706 public static class MyMediaRouteActionProvider extends MediaRouteActionProvider { 707 public MyMediaRouteActionProvider(Context context) { 708 super(context); 709 } 710 711 @Override 712 public boolean isVisible() { 713 return true; 714 } 715 } 716 717 public static class ControllerDialogFragment extends MediaRouteControllerDialogFragment { 718 private MediaRouteControllerDialog mControllerDialog; 719 private Player mPlayer; 720 private CheckBox mUseDefaultControlCheckBox; 721 722 public ControllerDialogFragment() { 723 super(); 724 } 725 726 public ControllerDialogFragment(Player player, CheckBox customControlViewCheckBox) { 727 mPlayer = player; 728 this.mUseDefaultControlCheckBox = customControlViewCheckBox; 729 } 730 731 @Override 732 public MediaRouteControllerDialog onCreateControllerDialog( 733 Context context, Bundle savedInstanceState) { 734 mControllerDialog = this.mUseDefaultControlCheckBox.isChecked() 735 ? super.onCreateControllerDialog(context, savedInstanceState) 736 : new MyMediaRouteControllerDialog(context); 737 mControllerDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 738 @Override 739 public void onDismiss(DialogInterface dialog) { 740 mControllerDialog = null; 741 } 742 }); 743 return mControllerDialog; 744 } 745 746 public void setPlayer(Player player) { 747 mPlayer = player; 748 } 749 } 750} 751