PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

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

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