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