• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.supportv4.media;
18 
19 //BEGIN_INCLUDE(complete)
20 import android.support.v4.media.TransportMediator;
21 import android.support.v4.media.TransportPerformer;
22 import com.example.android.supportv4.R;
23 
24 import android.app.ActionBar;
25 import android.content.Context;
26 import android.media.MediaPlayer;
27 import android.os.Handler;
28 import android.util.AttributeSet;
29 import android.view.KeyEvent;
30 import android.view.View;
31 
32 import android.app.Activity;
33 import android.net.Uri;
34 import android.os.Bundle;
35 import android.widget.VideoView;
36 
37 public class TransportControllerActivity extends Activity {
38 
39     /**
40      * TODO: Set the path variable to a streaming video URL or a local media
41      * file path.
42      */
43     private Content mContent;
44     private TransportMediator mTransportMediator;
45     private MediaController mMediaController;
46 
47     /**
48      * Handle actions from on-screen media controls.  Most of these are simple re-directs
49      * to the VideoView; some we need to capture to update our state.
50      */
51     TransportPerformer mTransportPerformer = new TransportPerformer() {
52         @Override public void onStart() {
53             mContent.start();
54         }
55 
56         @Override public void onStop() {
57             mContent.pause();
58         }
59 
60         @Override public void onPause() {
61             mContent.pause();
62         }
63 
64         @Override public long onGetDuration() {
65             return mContent.getDuration();
66         }
67 
68         @Override public long onGetCurrentPosition() {
69             return mContent.getCurrentPosition();
70         }
71 
72         @Override public void onSeekTo(long pos) {
73             mContent.seekTo((int)pos);
74         }
75 
76         @Override public boolean onIsPlaying() {
77             return mContent.isPlaying();
78         }
79 
80         @Override public int onGetBufferPercentage() {
81             return mContent.getBufferPercentage();
82         }
83 
84         @Override public int onGetTransportControlFlags() {
85             int flags = TransportMediator.FLAG_KEY_MEDIA_PLAY
86                     | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE
87                     | TransportMediator.FLAG_KEY_MEDIA_STOP;
88             if (mContent.canPause()) {
89                 flags |= TransportMediator.FLAG_KEY_MEDIA_PAUSE;
90             }
91             if (mContent.canSeekBackward()) {
92                 flags |= TransportMediator.FLAG_KEY_MEDIA_REWIND;
93             }
94             if (mContent.canSeekForward()) {
95                 flags |= TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD;
96             }
97             return flags;
98         }
99     };
100 
101     /**
102      * This is the actual video player.  It is the top-level content of
103      * the activity's view hierarchy, going under the status bar and nav
104      * bar areas.
105      */
106     public static class Content extends VideoView implements
107             View.OnSystemUiVisibilityChangeListener, View.OnClickListener,
108             ActionBar.OnMenuVisibilityListener, MediaPlayer.OnPreparedListener,
109             MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
110         Activity mActivity;
111         TransportMediator mTransportMediator;
112         MediaController mMediaController;
113         boolean mAddedMenuListener;
114         boolean mMenusOpen;
115         boolean mPaused;
116         boolean mNavVisible;
117         int mLastSystemUiVis;
118 
119         Runnable mNavHider = new Runnable() {
120             @Override public void run() {
121                 setNavVisibility(false);
122             }
123         };
124 
125         Runnable mProgressUpdater = new Runnable() {
126             @Override public void run() {
127                 mMediaController.updateProgress();
128                 getHandler().postDelayed(this, 1000);
129             }
130         };
131 
Content(Context context, AttributeSet attrs)132         public Content(Context context, AttributeSet attrs) {
133             super(context, attrs);
134             setOnSystemUiVisibilityChangeListener(this);
135             setOnClickListener(this);
136             setOnPreparedListener(this);
137             setOnCompletionListener(this);
138             setOnErrorListener(this);
139         }
140 
init(Activity activity, TransportMediator transportMediator, MediaController mediaController)141         public void init(Activity activity, TransportMediator transportMediator,
142                 MediaController mediaController) {
143             // This called by the containing activity to supply the surrounding
144             // state of the video player that it will interact with.
145             mActivity = activity;
146             mTransportMediator = transportMediator;
147             mMediaController = mediaController;
148             pause();
149         }
150 
onAttachedToWindow()151         @Override protected void onAttachedToWindow() {
152             super.onAttachedToWindow();
153             if (mActivity != null) {
154                 mAddedMenuListener = true;
155                 mActivity.getActionBar().addOnMenuVisibilityListener(this);
156             }
157         }
158 
onDetachedFromWindow()159         @Override protected void onDetachedFromWindow() {
160             super.onDetachedFromWindow();
161             if (mAddedMenuListener) {
162                 mActivity.getActionBar().removeOnMenuVisibilityListener(this);
163             }
164             mNavVisible = false;
165         }
166 
onSystemUiVisibilityChange(int visibility)167         @Override public void onSystemUiVisibilityChange(int visibility) {
168             // Detect when we go out of nav-hidden mode, to clear our state
169             // back to having the full UI chrome up.  Only do this when
170             // the state is changing and nav is no longer hidden.
171             int diff = mLastSystemUiVis ^ visibility;
172             mLastSystemUiVis = visibility;
173             if ((diff&SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
174                     && (visibility&SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
175                 setNavVisibility(true);
176             }
177         }
178 
onWindowVisibilityChanged(int visibility)179         @Override protected void onWindowVisibilityChanged(int visibility) {
180             super.onWindowVisibilityChanged(visibility);
181 
182             // When we become visible or invisible, play is paused.
183             pause();
184         }
185 
onClick(View v)186         @Override public void onClick(View v) {
187             // Clicking anywhere makes the navigation visible.
188             setNavVisibility(true);
189         }
190 
onMenuVisibilityChanged(boolean isVisible)191         @Override public void onMenuVisibilityChanged(boolean isVisible) {
192             mMenusOpen = isVisible;
193             setNavVisibility(true);
194         }
195 
196         @Override
onPrepared(MediaPlayer mp)197         public void onPrepared(MediaPlayer mp) {
198             mMediaController.setEnabled(true);
199         }
200 
201         @Override
onCompletion(MediaPlayer mp)202         public void onCompletion(MediaPlayer mp) {
203             mTransportMediator.pausePlaying();
204             pause();
205         }
206 
207         @Override
onError(MediaPlayer mp, int what, int extra)208         public boolean onError(MediaPlayer mp, int what, int extra) {
209             mTransportMediator.pausePlaying();
210             pause();
211             return false;
212         }
213 
start()214         @Override public void start() {
215             super.start();
216             mPaused = false;
217             setKeepScreenOn(true);
218             setNavVisibility(true);
219             mMediaController.refresh();
220             scheduleProgressUpdater();
221         }
222 
pause()223         @Override public void pause() {
224             super.pause();
225             mPaused = true;
226             setKeepScreenOn(false);
227             setNavVisibility(true);
228             mMediaController.refresh();
229             scheduleProgressUpdater();
230         }
231 
scheduleProgressUpdater()232         void scheduleProgressUpdater() {
233             Handler h = getHandler();
234             if (h != null) {
235                 if (mNavVisible && !mPaused) {
236                     h.removeCallbacks(mProgressUpdater);
237                     h.post(mProgressUpdater);
238                 } else {
239                     h.removeCallbacks(mProgressUpdater);
240                 }
241             }
242         }
243 
setNavVisibility(boolean visible)244         void setNavVisibility(boolean visible) {
245             int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
246                     | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
247                     | SYSTEM_UI_FLAG_LAYOUT_STABLE;
248             if (!visible) {
249                 newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN
250                         | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
251             }
252 
253             // If we are now visible, schedule a timer for us to go invisible.
254             if (visible) {
255                 Handler h = getHandler();
256                 if (h != null) {
257                     h.removeCallbacks(mNavHider);
258                     if (!mMenusOpen && !mPaused) {
259                         // If the menus are open or play is paused, we will not auto-hide.
260                         h.postDelayed(mNavHider, 3000);
261                     }
262                 }
263             }
264 
265             // Set the new desired visibility.
266             setSystemUiVisibility(newVis);
267             mNavVisible = visible;
268             mMediaController.setVisibility(visible ? VISIBLE : INVISIBLE);
269             scheduleProgressUpdater();
270         }
271     }
272 
273     @Override
onCreate(Bundle icicle)274     public void onCreate(Bundle icicle) {
275         super.onCreate(icicle);
276         setContentView(R.layout.videoview);
277 
278         // Find the video player in our UI.
279         mContent = (Content) findViewById(R.id.content);
280 
281         // Create transport controller to control video, giving the callback
282         // interface to receive actions from.
283         mTransportMediator = new TransportMediator(this, mTransportPerformer);
284 
285         // Create and initialize the media control UI.
286         mMediaController = (MediaController) findViewById(R.id.media_controller);
287         mMediaController.setMediaPlayer(mTransportMediator);
288 
289         // We're just playing a built-in demo video.
290         mContent.init(this, mTransportMediator, mMediaController);
291         mContent.setVideoURI(Uri.parse("android.resource://" + getPackageName() +
292                 "/" + R.raw.videoviewdemo));
293     }
294 
295     @Override
dispatchKeyEvent(KeyEvent event)296     public boolean dispatchKeyEvent(KeyEvent event) {
297         // We first dispatch keys to the transport controller -- we want it
298         // to get to consume any media keys rather than letting whoever has focus
299         // in the view hierarchy to potentially eat it.
300         if (mTransportMediator.dispatchKeyEvent(event)) {
301             return true;
302         }
303 
304         return super.dispatchKeyEvent(event);
305     }
306 }
307 //END_INCLUDE(complete)
308