PageRenderTime 56ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java

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