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