1ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown/*
2ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Copyright (C) 2013 The Android Open Source Project
3ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
4ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * you may not use this file except in compliance with the License.
6ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * You may obtain a copy of the License at
7ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
8ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
10ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Unless required by applicable law or agreed to in writing, software
11ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * See the License for the specific language governing permissions and
14ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * limitations under the License.
15ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown */
16ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
17ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownpackage com.example.android.supportv7.media;
18ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
1944d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.app.PendingIntent;
207578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.content.ComponentName;
2157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.Context;
225d429bc3a8195d6f37cf2f7da0935972950539b4RoboErikimport android.content.DialogInterface;
23ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.content.Intent;
247578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.AudioManager;
257578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.AudioManager.OnAudioFocusChangeListener;
26ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.net.Uri;
2761636870e0a12db5909955eca58e0070357dde42Donghyun Choimport android.os.Build;
2844d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.os.Bundle;
2945ca8fb42505658590e808d4d30b57598689d9a8Jeff Brownimport android.os.Environment;
3057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.os.Handler;
3157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.os.SystemClock;
320e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moonimport android.provider.Settings;
339a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErikimport android.support.v4.media.session.MediaSessionCompat;
34ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.util.Log;
357578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.view.KeyEvent;
36ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.Menu;
37ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.MenuItem;
38ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.View;
39ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.View.OnClickListener;
4057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.ViewGroup;
41ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.AdapterView;
4257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.AdapterView.OnItemClickListener;
43ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.ArrayAdapter;
4476d965dc41863b33f887db33d283cb7f1523f60dJae Seoimport android.widget.CheckBox;
4557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.ImageButton;
46ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.ListView;
4757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.SeekBar;
4857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.SeekBar.OnSeekBarChangeListener;
4944d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.widget.TabHost;
5044d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.widget.TabHost.OnTabChangeListener;
5144d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.widget.TabHost.TabSpec;
5244d25261c2a38c81f1eea123de3986b453b9afeeChris Banesimport android.widget.TextView;
535d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
54def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.appcompat.app.AppCompatActivity;
55def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.core.view.MenuItemCompat;
56def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.fragment.app.FragmentManager;
57def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.app.MediaRouteActionProvider;
58def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.app.MediaRouteControllerDialog;
59def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.app.MediaRouteControllerDialogFragment;
60def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.app.MediaRouteDialogFactory;
61def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.app.MediaRouteDiscoveryFragment;
62def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaControlIntent;
63def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaItemStatus;
64def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaRouteSelector;
65def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaRouter;
66def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaRouter.Callback;
67def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaRouter.ProviderInfo;
68def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.mediarouter.media.MediaRouter.RouteInfo;
69def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikas
70c1a24039658cc52f34046800790de302b7db075bSungsoo Limimport com.example.android.supportv7.R;
71c1a24039658cc52f34046800790de302b7db075bSungsoo Lim
7257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport java.io.File;
73ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
74ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown/**
75ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * <h3>Media Router Support Activity</h3>
76ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
77ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * <p>
78ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * This demonstrates how to use the {@link MediaRouter} API to build an
79ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * application that allows the user to send content to various rendering
80ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * targets.
81ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * </p>
82ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown */
8344d25261c2a38c81f1eea123de3986b453b9afeeChris Banespublic class SampleMediaRouterActivity extends AppCompatActivity {
84a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private static final String TAG = "SampleMediaRouterActivity";
85f0dd451048100915f072423730a93d17c53fd899Jeff Brown    private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment";
8676d965dc41863b33f887db33d283cb7f1523f60dJae Seo    private static final boolean ENABLE_DEFAULT_CONTROL_CHECK_BOX = false;
87ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
88ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private MediaRouter mMediaRouter;
8955e47d370890d3cbdab82857090c42df734ba276Jeff Brown    private MediaRouteSelector mSelector;
9057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private LibraryAdapter mLibraryItems;
9157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private PlaylistAdapter mPlayListItems;
92ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private TextView mInfoTextView;
9357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ListView mLibraryView;
9457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ListView mPlayListView;
9576d965dc41863b33f887db33d283cb7f1523f60dJae Seo    private CheckBox mUseDefaultControlCheckBox;
9657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ImageButton mPauseResumeButton;
9757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ImageButton mStopButton;
9857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private SeekBar mSeekBar;
9957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean mNeedResume;
10057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean mSeeking;
10157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
10257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final Handler mHandler = new Handler();
10357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final Runnable mUpdateSeekRunnable = new Runnable() {
10457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
10557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void run() {
106a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            updateProgress();
10757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // update Ui every 1 second
10857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mHandler.postDelayed(this, 1000);
10957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
11057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
11157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
112a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private final SessionManager mSessionManager = new SessionManager("app");
11357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private Player mPlayer;
11457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
11557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final MediaRouter.Callback mMediaRouterCB = new MediaRouter.Callback() {
11657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Return a custom callback that will simply log all of the route events
11757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // for demonstration purposes.
11857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
11957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteAdded(MediaRouter router, RouteInfo route) {
12057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteAdded: route=" + route);
12157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
12257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
12357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
12457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteChanged(MediaRouter router, RouteInfo route) {
12557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteChanged: route=" + route);
12657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
12757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
12857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
12957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteRemoved(MediaRouter router, RouteInfo route) {
13057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteRemoved: route=" + route);
13157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
13257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
13357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
13457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteSelected(MediaRouter router, RouteInfo route) {
13557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteSelected: route=" + route);
13657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
1379a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            mPlayer = Player.create(SampleMediaRouterActivity.this, route, mMediaSession);
13861636870e0a12db5909955eca58e0070357dde42Donghyun Cho            if (isPresentationApiSupported()) {
13961636870e0a12db5909955eca58e0070357dde42Donghyun Cho                mPlayer.updatePresentation();
14061636870e0a12db5909955eca58e0070357dde42Donghyun Cho            }
141a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mSessionManager.setPlayer(mPlayer);
142a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mSessionManager.unsuspend();
14357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
14457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
14557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
14657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
14757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
14857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
14957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteUnselected: route=" + route);
1509a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            mMediaSession.setActive(false);
151a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang
152a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            PlaylistItem item = getCheckedPlaylistItem();
153a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            if (item != null) {
154cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                long pos = item.getPosition() + (mSessionManager.isPaused() ?
155a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        0 : (SystemClock.elapsedRealtime() - item.getTimestamp()));
156a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                mSessionManager.suspend(pos);
157a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            }
15861636870e0a12db5909955eca58e0070357dde42Donghyun Cho            if (isPresentationApiSupported()) {
15961636870e0a12db5909955eca58e0070357dde42Donghyun Cho                mPlayer.updatePresentation();
16061636870e0a12db5909955eca58e0070357dde42Donghyun Cho            }
161a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mPlayer.release();
16257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
16357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
16457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
16557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
16657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteVolumeChanged: route=" + route);
16757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
16857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
16957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
17057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRoutePresentationDisplayChanged(
17157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter router, RouteInfo route) {
17257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
17361636870e0a12db5909955eca58e0070357dde42Donghyun Cho            if (isPresentationApiSupported()) {
17461636870e0a12db5909955eca58e0070357dde42Donghyun Cho                mPlayer.updatePresentation();
17561636870e0a12db5909955eca58e0070357dde42Donghyun Cho            }
17657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
17757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
17857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
17957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
18057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
18157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
18257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
18357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
18457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
18557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
18657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
18757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
18857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
18957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
19057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
19157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
19261636870e0a12db5909955eca58e0070357dde42Donghyun Cho
19361636870e0a12db5909955eca58e0070357dde42Donghyun Cho        private boolean isPresentationApiSupported() {
19461636870e0a12db5909955eca58e0070357dde42Donghyun Cho            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
19561636870e0a12db5909955eca58e0070357dde42Donghyun Cho        }
19657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
19757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
1989a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik    private MediaSessionCompat mMediaSession;
1997578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private ComponentName mEventReceiver;
2007578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private AudioManager mAudioManager;
2017578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private PendingIntent mMediaPendingIntent;
2027578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private final OnAudioFocusChangeListener mAfChangeListener =
2037578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            new OnAudioFocusChangeListener() {
2047578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        @Override
2057578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        public void onAudioFocusChange(int focusChange) {
2067578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
2077578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: LOSS_TRANSIENT");
2087578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
2097578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_GAIN");
2107578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
2117578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_LOSS");
2127578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            }
2137578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
2147578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    };
2157578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
216ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
217ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    protected void onCreate(Bundle savedInstanceState) {
218ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
219ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        super.onCreate(savedInstanceState);
220ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
2210e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon        // Need overlay permission for emulating remote display.
2220e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon        if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {
2230e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
2240e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon                    Uri.parse("package:" + getPackageName()));
2250e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon            startActivityForResult(intent, 0);
2260e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon        }
2270e573df7dcd4a3062e76627f26ee2ee377eebfaeHyundo Moon
228ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Get the media router service.
229ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        mMediaRouter = MediaRouter.getInstance(this);
230ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
23155e47d370890d3cbdab82857090c42df734ba276Jeff Brown        // Create a route selector for the type of routes that we care about.
23255e47d370890d3cbdab82857090c42df734ba276Jeff Brown        mSelector = new MediaRouteSelector.Builder()
23355e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
23455e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
23555e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
23655e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE)
23755e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .build();
238f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo
239f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        // Add a fragment to take care of media route discovery.
240f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        // This fragment automatically adds or removes a callback whenever the activity
241f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        // is started or stopped.
242f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        FragmentManager fm = getSupportFragmentManager();
243f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        DiscoveryFragment fragment = (DiscoveryFragment) fm.findFragmentByTag(
244f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo                DISCOVERY_FRAGMENT_TAG);
245f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        if (fragment == null) {
24611cd4963ab66125d66342bde773559da74611cd5Donghyun Cho            fragment = new DiscoveryFragment();
247f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            fm.beginTransaction()
248f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo                    .add(fragment, DISCOVERY_FRAGMENT_TAG)
249f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo                    .commit();
250f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        }
25111cd4963ab66125d66342bde773559da74611cd5Donghyun Cho        fragment.setCallback(mMediaRouterCB);
25211cd4963ab66125d66342bde773559da74611cd5Donghyun Cho        fragment.setRouteSelector(mSelector);
253f0dd451048100915f072423730a93d17c53fd899Jeff Brown
25457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Populate an array adapter with streaming media items.
255ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        String[] mediaNames = getResources().getStringArray(R.array.media_names);
256ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        String[] mediaUris = getResources().getStringArray(R.array.media_uris);
25757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryItems = new LibraryAdapter();
258ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        for (int i = 0; i < mediaNames.length; i++) {
25957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mLibraryItems.add(new MediaItem(
260a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    "[streaming] "+mediaNames[i], Uri.parse(mediaUris[i]), "video/mp4"));
261ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
262ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
26345ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown        // Scan local external storage directory for media files.
26445ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown        File externalDir = Environment.getExternalStorageDirectory();
26545ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown        if (externalDir != null) {
26645ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown            File list[] = externalDir.listFiles();
26745ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown            if (list != null) {
26845ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                for (int i = 0; i < list.length; i++) {
26945ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                    String filename = list[i].getName();
27045ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                    if (filename.matches(".*\\.(m4v|mp4)")) {
27145ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                        mLibraryItems.add(new MediaItem("[local] " + filename,
272a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                                Uri.fromFile(list[i]), "video/mp4"));
27345ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                    }
27445ca8fb42505658590e808d4d30b57598689d9a8Jeff Brown                }
27557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
27657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
27757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
27857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListItems = new PlaylistAdapter();
27957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
280ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Initialize the layout.
281ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        setContentView(R.layout.sample_media_router);
282ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
28357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabHost tabHost=(TabHost)findViewById(R.id.tabHost);
28457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.setup();
28557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        String tabName = getResources().getString(R.string.library_tab_text);
28657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec1=tabHost.newTabSpec(tabName);
28757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec1.setContent(R.id.tab1);
28857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec1.setIndicator(tabName);
28957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
29057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabName = getResources().getString(R.string.playlist_tab_text);
29157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec2=tabHost.newTabSpec(tabName);
29257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec2.setIndicator(tabName);
29357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec2.setContent(R.id.tab2);
29457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
295cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        tabName = getResources().getString(R.string.info_tab_text);
29657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec3=tabHost.newTabSpec(tabName);
29757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec3.setIndicator(tabName);
29857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec3.setContent(R.id.tab3);
29957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
30057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec1);
30157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec2);
30257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec3);
30357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.setOnTabChangedListener(new OnTabChangeListener() {
30457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
30557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onTabChanged(String arg0) {
30657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateUi();
30757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
30857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
30957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
310fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mLibraryView = findViewById(R.id.media);
31157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setAdapter(mLibraryItems);
31257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
31357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setOnItemClickListener(new OnItemClickListener() {
31457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
31557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
31657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateButtons();
31757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
31857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
319ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
320fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mPlayListView = findViewById(R.id.playlist);
32157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setAdapter(mPlayListItems);
32257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
32357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setOnItemClickListener(new OnItemClickListener() {
324ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
325ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
326ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown                updateButtons();
327ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
328ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
329ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
330fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mInfoTextView = findViewById(R.id.info);
33157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
332fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mUseDefaultControlCheckBox = findViewById(R.id.custom_control_view_checkbox);
33376d965dc41863b33f887db33d283cb7f1523f60dJae Seo        if (ENABLE_DEFAULT_CONTROL_CHECK_BOX) {
33476d965dc41863b33f887db33d283cb7f1523f60dJae Seo            mUseDefaultControlCheckBox.setVisibility(View.VISIBLE);
33576d965dc41863b33f887db33d283cb7f1523f60dJae Seo        }
33657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPauseResumeButton = (ImageButton)findViewById(R.id.pause_resume_button);
33757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPauseResumeButton.setOnClickListener(new OnClickListener() {
338ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
339ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onClick(View v) {
340cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                if (mSessionManager.isPaused()) {
341a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    mSessionManager.resume();
342cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                } else {
343cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                    mSessionManager.pause();
34457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
345ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
346ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
347ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
34857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mStopButton = (ImageButton)findViewById(R.id.stop_button);
34957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mStopButton.setOnClickListener(new OnClickListener() {
350ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
351ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onClick(View v) {
352a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                mSessionManager.stop();
353ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
354ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
35557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
356fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mSeekBar = findViewById(R.id.seekbar);
35757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
35857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
35957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
360a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                PlaylistItem item = getCheckedPlaylistItem();
361a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                if (fromUser && item != null && item.getDuration() > 0) {
362a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    long pos = progress * item.getDuration() / 100;
363a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    mSessionManager.seek(item.getItemId(), pos);
364a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    item.setPosition(pos);
365a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    item.setTimestamp(SystemClock.elapsedRealtime());
36657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
36757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
36857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
36957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onStartTrackingTouch(SeekBar seekBar) {
37057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSeeking = true;
37157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
37257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
37357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onStopTrackingTouch(SeekBar seekBar) {
37457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSeeking = false;
37557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateUi();
37657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
37757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
37857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
37957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Schedule Ui update
38057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mHandler.postDelayed(mUpdateSeekRunnable, 1000);
38157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
3827578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        // Build the PendingIntent for the remote control client
3837578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
3847578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mEventReceiver = new ComponentName(getPackageName(),
3857578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                SampleMediaButtonReceiver.class.getName());
3867578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
3877578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mediaButtonIntent.setComponent(mEventReceiver);
3887578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mMediaPendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
3897b95dd38981772983f00c5ed91aca4b30b782facJeff Brown
3907b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        // Create and register the remote control client
3919a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        createMediaSession();
3929a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        mMediaRouter.setMediaSessionCompat(mMediaSession);
393a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang
394a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        // Set up playback manager and player
395a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mPlayer = Player.create(SampleMediaRouterActivity.this,
3969a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                mMediaRouter.getSelectedRoute(), mMediaSession);
3975d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
398a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mSessionManager.setPlayer(mPlayer);
399a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mSessionManager.setCallback(new SessionManager.Callback() {
400a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            @Override
401a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            public void onStatusChanged() {
402a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                updateUi();
403a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            }
404a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang
405a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            @Override
406a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            public void onItemChanged(PlaylistItem item) {
407a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            }
408a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        });
409a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang
410a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        updateUi();
4117578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
4127578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4139a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik    private void createMediaSession() {
4149a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        // Create the MediaSession
4159a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        mMediaSession = new MediaSessionCompat(this, "SampleMediaRouter", mEventReceiver,
4169a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                mMediaPendingIntent);
4179a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
4189a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
4199a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        mMediaSession.setCallback(new MediaSessionCompat.Callback() {
4209a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            @Override
4219a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
4229a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                if (mediaButtonEvent != null) {
4239a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                    return handleMediaKey(
4249a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                            (KeyEvent) mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
4259a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                }
4269a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                return super.onMediaButtonEvent(mediaButtonEvent);
4279a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            }
4287578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4299a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            @Override
4309a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            public void onPlay() {
4319a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                mSessionManager.resume();
4329a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            }
4339a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik
4349a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            @Override
4359a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            public void onPause() {
4369a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                mSessionManager.pause();
4379a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik            }
4389a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        });
4399a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik
4409a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        SampleMediaButtonReceiver.setActivity(SampleMediaRouterActivity.this);
4417578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
4427578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4437578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean handleMediaKey(KeyEvent event) {
4449a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        if (event != null && event.getAction() == KeyEvent.ACTION_DOWN
4459a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                && event.getRepeatCount() == 0) {
4467578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            switch (event.getKeyCode()) {
4477578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
4489a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik                case KeyEvent.KEYCODE_HEADSETHOOK:
4497578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
4507578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Play/Pause event from RemoteControlClient");
451cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                    if (mSessionManager.isPaused()) {
452a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        mSessionManager.resume();
453cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                    } else {
454cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                        mSessionManager.pause();
4557578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
4567578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
4577578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
4587578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PLAY:
4597578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
4607578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Play event from RemoteControlClient");
461cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                    if (mSessionManager.isPaused()) {
462a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        mSessionManager.resume();
4637578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
4647578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
4657578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
4667578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PAUSE:
4677578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
4687578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Pause event from RemoteControlClient");
469cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                    if (!mSessionManager.isPaused()) {
470a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        mSessionManager.pause();
4717578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
4727578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
4737578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
4747578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_STOP:
4757578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
4767578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Stop event from RemoteControlClient");
477a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    mSessionManager.stop();
4787578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
4797578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
4807578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                default:
4817578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    break;
4827578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            }
4837578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
4847578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return false;
4857578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
4867578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4877578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    @Override
4887578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean onKeyDown(int keyCode, KeyEvent event) {
4897578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return handleMediaKey(event) || super.onKeyDown(keyCode, event);
4907578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
4917578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4927578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    @Override
4937578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean onKeyUp(int keyCode, KeyEvent event) {
4947578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return handleMediaKey(event) || super.onKeyUp(keyCode, event);
495ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
496ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
497ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
498f0dd451048100915f072423730a93d17c53fd899Jeff Brown    public void onStart() {
499ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
500f0dd451048100915f072423730a93d17c53fd899Jeff Brown        super.onStart();
50157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
502ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
50357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
50457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onPause() {
50557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // pause media player for local playback case only
506cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        if (!mPlayer.isRemotePlayback() && !mSessionManager.isPaused()) {
50757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mNeedResume = true;
508a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mSessionManager.pause();
50957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
51057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onPause();
51157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
51257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
51357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
51457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onResume() {
51557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // resume media player for local playback case only
516a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        if (!mPlayer.isRemotePlayback() && mNeedResume) {
517a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mSessionManager.resume();
51857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mNeedResume = false;
51957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
52057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onResume();
52157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
52257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
52357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
52457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onDestroy() {
525a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mSessionManager.stop();
526a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mPlayer.release();
5279a2de97bec8126f8c8c05e9c995f378c5a73319aRoboErik        mMediaSession.release();
52857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onDestroy();
529ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
530ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
531ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
532ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    public boolean onCreateOptionsMenu(Menu menu) {
533ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
534ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        super.onCreateOptionsMenu(menu);
535ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
536ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Inflate the menu and configure the media router action provider.
537ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);
538ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
53955e47d370890d3cbdab82857090c42df734ba276Jeff Brown        MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
540f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        MediaRouteActionProvider mediaRouteActionProvider =
541f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo                (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
54255e47d370890d3cbdab82857090c42df734ba276Jeff Brown        mediaRouteActionProvider.setRouteSelector(mSelector);
543cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() {
544cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang            @Override
545cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang            public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() {
54676d965dc41863b33f887db33d283cb7f1523f60dJae Seo                return new ControllerDialogFragment(mPlayer, mUseDefaultControlCheckBox);
547cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang            }
548cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        });
549ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
550ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Return true to show the menu.
551ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        return true;
552ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
553ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
554a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private void updateProgress() {
55557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Estimate content position from last status time and elapsed time.
55657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // (Note this might be slightly out of sync with remote side, however
55757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // it avoids frequent polling the MRP.)
55857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int progress = 0;
559a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        PlaylistItem item = getCheckedPlaylistItem();
560a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        if (item != null) {
561a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            int state = item.getState();
562a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            long duration = item.getDuration();
56357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (duration <= 0) {
56457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING
56557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        || state == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
566a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                    mSessionManager.updateStatus();
56757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
56857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
569a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                long position = item.getPosition();
570cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang                long timeDelta = mSessionManager.isPaused() ? 0 :
571a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        (SystemClock.elapsedRealtime() - item.getTimestamp());
57257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                progress = (int)(100.0 * (position + timeDelta) / duration);
57357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
574ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
57557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar.setProgress(progress);
57657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
577ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
57857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void updateUi() {
57957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        updatePlaylist();
580a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        updateRouteDescription();
58157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        updateButtons();
58270f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho        if (mPlayer != null && mSessionManager != null) {
58370f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho            PlaylistItem currentItem = mSessionManager.getCurrentItem();
58470f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho            if (currentItem != null) {
58570f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                mPlayer.updateMetadata(currentItem);
58670f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                int currentItemState = Player.STATE_IDLE;
58770f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                switch(currentItem.getState()) {
58870f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                    case MediaItemStatus.PLAYBACK_STATE_PLAYING:
58970f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        currentItemState = Player.STATE_PLAYING;
59070f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        break;
59170f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                    case MediaItemStatus.PLAYBACK_STATE_PAUSED:
59270f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        currentItemState = Player.STATE_PAUSED;
59370f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        break;
59470f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                    case MediaItemStatus.PLAYBACK_STATE_PENDING:
59570f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                    case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
59670f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        currentItemState = Player.STATE_PREPARING_FOR_PLAY;
59770f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        break;
59870f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                }
59970f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                mPlayer.publishState(currentItemState);
60070f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho            }
601cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        }
602ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
603ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
60457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void updatePlaylist() {
60557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListItems.clear();
606a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        for (PlaylistItem item : mSessionManager.getPlaylist()) {
607a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mPlayListItems.add(item);
608a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        }
60957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.invalidate();
610a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    }
611ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
612a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private void updateRouteDescription() {
613a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        RouteInfo route = mMediaRouter.getSelectedRoute();
614a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mInfoTextView.setText("Currently selected route:"
615a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                + "\nName: " + route.getName()
61670f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                + "\nProvider: " + route.getProvider().getPackageName());
61757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
618fcb6a9d1caaf43ae41f859ebb58a4483b12475a1Jeff Brown
619a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private void updateButtons() {
620a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
621a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        // show pause or resume icon depending on current state
622cf61a6ed2bfa6141b832fdc40a9fbfb70af91416Chong Zhang        mPauseResumeButton.setImageResource(mSessionManager.isPaused() ?
623a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                R.drawable.ic_media_play : R.drawable.ic_media_pause);
624a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        // only enable seek bar when duration is known
625a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        PlaylistItem item = getCheckedPlaylistItem();
626a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        mSeekBar.setEnabled(item != null && item.getDuration() > 0);
62757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
628ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
629a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private PlaylistItem getCheckedPlaylistItem() {
63057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int count = mPlayListView.getCount();
63157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int index = mPlayListView.getCheckedItemPosition();
63257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (count > 0) {
63357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (index < 0 || index >= count) {
63457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                index = 0;
63557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayListView.setItemChecked(0, true);
63657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
63757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return mPlayListItems.getItem(index);
638ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
63957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        return null;
640ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
641ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
642f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo    /**
643f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo     * Media route discovery fragment.
644f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo     */
645f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo    public static final class DiscoveryFragment extends MediaRouteDiscoveryFragment {
646f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        private static final String TAG = "DiscoveryFragment";
647f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        private Callback mCallback;
648f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo
649f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        public void setCallback(Callback cb) {
650f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            mCallback = cb;
651f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        }
652f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo
653f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        @Override
654f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        public Callback onCreateCallback() {
655f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            return mCallback;
656f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        }
657f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo
658f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        @Override
659f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        public int onPrepareCallbackFlags() {
660f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            // Add the CALLBACK_FLAG_UNFILTERED_EVENTS flag to ensure that we will
661f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            // observe and log all route events including those that are for routes
662f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            // that do not match our selector.  This is only for demonstration purposes
663f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            // and should not be needed by most applications.
664f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo            return super.onPrepareCallbackFlags()
665f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo                    | MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS;
666f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo        }
667f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo    }
668f796be9c80d6a62de61853a0cb1d98b440a3586fSungsoo
669ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private static final class MediaItem {
670ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public final String mName;
671ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public final Uri mUri;
672a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        public final String mMime;
673ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
674a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang        public MediaItem(String name, Uri uri, String mime) {
675ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            mName = name;
676ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            mUri = uri;
677a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            mMime = mime;
678ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
679ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
680ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        @Override
681ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public String toString() {
682ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            return mName;
683ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
684ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
68555e47d370890d3cbdab82857090c42df734ba276Jeff Brown
68657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final class LibraryAdapter extends ArrayAdapter<MediaItem> {
68757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public LibraryAdapter() {
68857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            super(SampleMediaRouterActivity.this, R.layout.media_item);
68957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
69057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
69157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
69257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public View getView(int position, View convertView, ViewGroup parent) {
69357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final View v;
69457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (convertView == null) {
69557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = getLayoutInflater().inflate(R.layout.media_item, null);
69657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
69757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = convertView;
69857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
69957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
70057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final MediaItem item = getItem(position);
70157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
70257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            TextView tv = (TextView)v.findViewById(R.id.item_text);
70357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            tv.setText(item.mName);
70457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
70557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
70657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setImageResource(R.drawable.ic_menu_add);
70757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setTag(item);
70857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setOnClickListener(new OnClickListener() {
70957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                @Override
71057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                public void onClick(View v) {
71157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (item != null) {
71270f3627685b55b2bc1b3f0c17c9c30aa3a7fd062Donghyun Cho                        mSessionManager.add(item.mName, item.mUri, item.mMime);
71357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
71457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
71557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            });
71657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
71757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return v;
71857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
71957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
72057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
721a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang    private final class PlaylistAdapter extends ArrayAdapter<PlaylistItem> {
72257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public PlaylistAdapter() {
72357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            super(SampleMediaRouterActivity.this, R.layout.media_item);
72457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
72557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
72657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
72757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public View getView(int position, View convertView, ViewGroup parent) {
72857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final View v;
72957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (convertView == null) {
73057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = getLayoutInflater().inflate(R.layout.media_item, null);
73157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
73257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = convertView;
73357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
73457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
735a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang            final PlaylistItem item = getItem(position);
73657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
73757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            TextView tv = (TextView)v.findViewById(R.id.item_text);
73857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            tv.setText(item.toString());
73957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
74057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
74157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setImageResource(R.drawable.ic_menu_delete);
74257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setTag(item);
74357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setOnClickListener(new OnClickListener() {
74457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                @Override
74557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                public void onClick(View v) {
74657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (item != null) {
747a6bf581f7a7a6326505569f0d1215d0ba84779d7Chong Zhang                        mSessionManager.remove(item.getItemId());
74857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
74957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
75057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            });
75157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
75257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return v;
75357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
75457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
75557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
75655e47d370890d3cbdab82857090c42df734ba276Jeff Brown    /**
75755e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * Trivial subclass of this activity used to provide another copy of the
75855e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * same activity using a light theme instead of the dark theme.
75955e47d370890d3cbdab82857090c42df734ba276Jeff Brown     */
76055e47d370890d3cbdab82857090c42df734ba276Jeff Brown    public static class Light extends SampleMediaRouterActivity {
76155e47d370890d3cbdab82857090c42df734ba276Jeff Brown    }
76255e47d370890d3cbdab82857090c42df734ba276Jeff Brown
76355e47d370890d3cbdab82857090c42df734ba276Jeff Brown    /**
76455e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * Trivial subclass of this activity used to provide another copy of the
76555e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * same activity using a light theme with dark action bar instead of the dark theme.
76655e47d370890d3cbdab82857090c42df734ba276Jeff Brown     */
76755e47d370890d3cbdab82857090c42df734ba276Jeff Brown    public static class LightWithDarkActionBar extends SampleMediaRouterActivity {
76855e47d370890d3cbdab82857090c42df734ba276Jeff Brown    }
7695d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
7705d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik    public static class ControllerDialogFragment extends MediaRouteControllerDialogFragment {
7715d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        private MediaRouteControllerDialog mControllerDialog;
7725d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        private Player mPlayer;
77376d965dc41863b33f887db33d283cb7f1523f60dJae Seo        private CheckBox mUseDefaultControlCheckBox;
7745d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
7755d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        public ControllerDialogFragment() {
7765d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            super();
7775d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        }
7785d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
77976d965dc41863b33f887db33d283cb7f1523f60dJae Seo        public ControllerDialogFragment(Player player, CheckBox customControlViewCheckBox) {
7805d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            mPlayer = player;
78176d965dc41863b33f887db33d283cb7f1523f60dJae Seo            this.mUseDefaultControlCheckBox = customControlViewCheckBox;
7825d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        }
7835d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
7845d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        @Override
7855d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        public MediaRouteControllerDialog onCreateControllerDialog(
7865d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik                Context context, Bundle savedInstanceState) {
78776d965dc41863b33f887db33d283cb7f1523f60dJae Seo            mControllerDialog = this.mUseDefaultControlCheckBox.isChecked()
78876d965dc41863b33f887db33d283cb7f1523f60dJae Seo                    ? super.onCreateControllerDialog(context, savedInstanceState)
78976d965dc41863b33f887db33d283cb7f1523f60dJae Seo                    : new MyMediaRouteControllerDialog(context);
7905d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            mControllerDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
7915d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik                @Override
7925d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik                public void onDismiss(DialogInterface dialog) {
7935d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik                    mControllerDialog = null;
7945d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik                }
7955d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            });
7965d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            return mControllerDialog;
7975d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        }
7985d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik
7995d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        public void setPlayer(Player player) {
8005d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik            mPlayer = player;
8015d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik        }
8025d429bc3a8195d6f37cf2f7da0935972950539b4RoboErik    }
803ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown}
804