MediaRouter / src / com.example.android.mediarouter / player /

MainActivity.java

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