diff --git a/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java b/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
index e5333d705..3bee59460 100644
--- a/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
@@ -167,7 +167,7 @@ public class VideoPlayerActivity extends Activity
h.removeCallbacks(mNavHider);
if (!mMenusOpen && !mPaused) {
// If the menus are open or play is paused, we will not auto-hide.
- h.postDelayed(mNavHider, 1500);
+ h.postDelayed(mNavHider, 3000);
}
}
}
diff --git a/samples/Support4Demos/res/layout/media_controller.xml b/samples/Support4Demos/res/layout/media_controller.xml
new file mode 100644
index 000000000..b5e58b184
--- /dev/null
+++ b/samples/Support4Demos/res/layout/media_controller.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Support4Demos/res/layout/videoview.xml b/samples/Support4Demos/res/layout/videoview.xml
index ff636b99a..abc1f7e51 100644
--- a/samples/Support4Demos/res/layout/videoview.xml
+++ b/samples/Support4Demos/res/layout/videoview.xml
@@ -1,14 +1,39 @@
+
+
-
-
-
+ />
+
+
+
+
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
new file mode 100644
index 000000000..e7f9e080b
--- /dev/null
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.supportv4.media;
+
+import com.example.android.supportv4.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ProgressBar;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import java.util.Formatter;
+import java.util.Locale;
+
+/**
+ * Helper for implementing media controls in an application.
+ * Use instead of the very useful android.widget.MediaController.
+ * This version is embedded inside of an application's layout.
+ */
+public class MediaController extends FrameLayout {
+
+ private MediaPlayerControl mPlayer;
+ private Context mContext;
+ private ProgressBar mProgress;
+ private TextView mEndTime, mCurrentTime;
+ private boolean mDragging;
+ private boolean mUseFastForward;
+ private boolean mFromXml;
+ private boolean mListenersSet;
+ private View.OnClickListener mNextListener, mPrevListener;
+ StringBuilder mFormatBuilder;
+ Formatter mFormatter;
+ private ImageButton mPauseButton;
+ private ImageButton mFfwdButton;
+ private ImageButton mRewButton;
+ private ImageButton mNextButton;
+ private ImageButton mPrevButton;
+
+ public MediaController(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ mUseFastForward = true;
+ mFromXml = true;
+ LayoutInflater inflate = (LayoutInflater)
+ mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflate.inflate(R.layout.media_controller, this, true);
+ initControllerView();
+ }
+
+ public MediaController(Context context, boolean useFastForward) {
+ super(context);
+ mContext = context;
+ mUseFastForward = useFastForward;
+ }
+
+ public MediaController(Context context) {
+ this(context, true);
+ }
+
+ public void setMediaPlayer(MediaPlayerControl player) {
+ mPlayer = player;
+ updatePausePlay();
+ }
+
+ private void initControllerView() {
+ mPauseButton = (ImageButton) findViewById(R.id.pause);
+ if (mPauseButton != null) {
+ mPauseButton.requestFocus();
+ mPauseButton.setOnClickListener(mPauseListener);
+ }
+
+ mFfwdButton = (ImageButton) findViewById(R.id.ffwd);
+ if (mFfwdButton != null) {
+ mFfwdButton.setOnClickListener(mFfwdListener);
+ if (!mFromXml) {
+ mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ mRewButton = (ImageButton) findViewById(R.id.rew);
+ if (mRewButton != null) {
+ mRewButton.setOnClickListener(mRewListener);
+ if (!mFromXml) {
+ mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ // By default these are hidden. They will be enabled when setPrevNextListeners() is called
+ mNextButton = (ImageButton) findViewById(R.id.next);
+ if (mNextButton != null && !mFromXml && !mListenersSet) {
+ mNextButton.setVisibility(View.GONE);
+ }
+ mPrevButton = (ImageButton) findViewById(R.id.prev);
+ if (mPrevButton != null && !mFromXml && !mListenersSet) {
+ mPrevButton.setVisibility(View.GONE);
+ }
+
+ mProgress = (ProgressBar) findViewById(R.id.mediacontroller_progress);
+ if (mProgress != null) {
+ if (mProgress instanceof SeekBar) {
+ SeekBar seeker = (SeekBar) mProgress;
+ seeker.setOnSeekBarChangeListener(mSeekListener);
+ }
+ mProgress.setMax(1000);
+ }
+
+ mEndTime = (TextView) findViewById(R.id.time);
+ mCurrentTime = (TextView) findViewById(R.id.time_current);
+ mFormatBuilder = new StringBuilder();
+ mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
+
+ installPrevNextListeners();
+ }
+
+ /**
+ * Disable pause or seek buttons if the stream cannot be paused or seeked.
+ * This requires the control interface to be a MediaPlayerControlExt
+ */
+ private void disableUnsupportedButtons() {
+ try {
+ if (mPauseButton != null && !mPlayer.canPause()) {
+ mPauseButton.setEnabled(false);
+ }
+ if (mRewButton != null && !mPlayer.canSeekBackward()) {
+ mRewButton.setEnabled(false);
+ }
+ if (mFfwdButton != null && !mPlayer.canSeekForward()) {
+ mFfwdButton.setEnabled(false);
+ }
+ } catch (IncompatibleClassChangeError ex) {
+ // We were given an old version of the interface, that doesn't have
+ // the canPause/canSeekXYZ methods. This is OK, it just means we
+ // assume the media can be paused and seeked, and so we don't disable
+ // the buttons.
+ }
+ }
+
+ public void refresh() {
+ updateProgress();
+ disableUnsupportedButtons();
+ updatePausePlay();
+ }
+
+ private String stringForTime(int timeMs) {
+ int totalSeconds = timeMs / 1000;
+
+ int seconds = totalSeconds % 60;
+ int minutes = (totalSeconds / 60) % 60;
+ int hours = totalSeconds / 3600;
+
+ mFormatBuilder.setLength(0);
+ if (hours > 0) {
+ return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
+ } else {
+ return mFormatter.format("%02d:%02d", minutes, seconds).toString();
+ }
+ }
+
+ public int updateProgress() {
+ if (mPlayer == null || mDragging) {
+ return 0;
+ }
+ int position = mPlayer.getCurrentPosition();
+ int duration = mPlayer.getDuration();
+ if (mProgress != null) {
+ if (duration > 0) {
+ // use long to avoid overflow
+ long pos = 1000L * position / duration;
+ mProgress.setProgress( (int) pos);
+ }
+ int percent = mPlayer.getBufferPercentage();
+ mProgress.setSecondaryProgress(percent * 10);
+ }
+
+ if (mEndTime != null)
+ mEndTime.setText(stringForTime(duration));
+ if (mCurrentTime != null)
+ mCurrentTime.setText(stringForTime(position));
+
+ return position;
+ }
+
+ private View.OnClickListener mPauseListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ doPauseResume();
+ }
+ };
+
+ private void updatePausePlay() {
+ if (mPauseButton == null)
+ return;
+
+ if (mPlayer.isPlaying()) {
+ mPauseButton.setImageResource(android.R.drawable.ic_media_pause);
+ } else {
+ mPauseButton.setImageResource(android.R.drawable.ic_media_play);
+ }
+ }
+
+ private void doPauseResume() {
+ if (mPlayer.isPlaying()) {
+ mPlayer.pause();
+ } else {
+ mPlayer.start();
+ }
+ updatePausePlay();
+ }
+
+ // There are two scenarios that can trigger the seekbar listener to trigger:
+ //
+ // The first is the user using the touchpad to adjust the posititon of the
+ // seekbar's thumb. In this case onStartTrackingTouch is called followed by
+ // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
+ // We're setting the field "mDragging" to true for the duration of the dragging
+ // session to avoid jumps in the position in case of ongoing playback.
+ //
+ // The second scenario involves the user operating the scroll ball, in this
+ // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
+ // we will simply apply the updated position without suspending regular updates.
+ private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
+ public void onStartTrackingTouch(SeekBar bar) {
+ mDragging = true;
+ }
+
+ public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
+ if (!fromuser) {
+ // We're not interested in programmatically generated changes to
+ // the progress bar's position.
+ return;
+ }
+
+ long duration = mPlayer.getDuration();
+ long newposition = (duration * progress) / 1000L;
+ mPlayer.seekTo( (int) newposition);
+ if (mCurrentTime != null)
+ mCurrentTime.setText(stringForTime( (int) newposition));
+ }
+
+ public void onStopTrackingTouch(SeekBar bar) {
+ mDragging = false;
+ updateProgress();
+ updatePausePlay();
+ }
+ };
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (mPauseButton != null) {
+ mPauseButton.setEnabled(enabled);
+ }
+ if (mFfwdButton != null) {
+ mFfwdButton.setEnabled(enabled);
+ }
+ if (mRewButton != null) {
+ mRewButton.setEnabled(enabled);
+ }
+ if (mNextButton != null) {
+ mNextButton.setEnabled(enabled && mNextListener != null);
+ }
+ if (mPrevButton != null) {
+ mPrevButton.setEnabled(enabled && mPrevListener != null);
+ }
+ if (mProgress != null) {
+ mProgress.setEnabled(enabled);
+ }
+ disableUnsupportedButtons();
+ super.setEnabled(enabled);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(MediaController.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(MediaController.class.getName());
+ }
+
+ private View.OnClickListener mRewListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ int pos = mPlayer.getCurrentPosition();
+ pos -= 5000; // milliseconds
+ mPlayer.seekTo(pos);
+ updateProgress();
+ }
+ };
+
+ private View.OnClickListener mFfwdListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ int pos = mPlayer.getCurrentPosition();
+ pos += 15000; // milliseconds
+ mPlayer.seekTo(pos);
+ updateProgress();
+ }
+ };
+
+ private void installPrevNextListeners() {
+ if (mNextButton != null) {
+ mNextButton.setOnClickListener(mNextListener);
+ mNextButton.setEnabled(mNextListener != null);
+ }
+
+ if (mPrevButton != null) {
+ mPrevButton.setOnClickListener(mPrevListener);
+ mPrevButton.setEnabled(mPrevListener != null);
+ }
+ }
+
+ public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
+ mNextListener = next;
+ mPrevListener = prev;
+ mListenersSet = true;
+
+ installPrevNextListeners();
+
+ if (mNextButton != null && !mFromXml) {
+ mNextButton.setVisibility(View.VISIBLE);
+ }
+ if (mPrevButton != null && !mFromXml) {
+ mPrevButton.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public interface MediaPlayerControl {
+ void start();
+ void pause();
+ int getDuration();
+ int getCurrentPosition();
+ void seekTo(int pos);
+ boolean isPlaying();
+ int getBufferPercentage();
+ boolean canPause();
+ boolean canSeekBackward();
+ boolean canSeekForward();
+ }
+}
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java b/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
index e6d28a766..a4e0951ce 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
@@ -16,13 +16,19 @@
package com.example.android.supportv4.media;
-import android.view.KeyEvent;
import com.example.android.supportv4.R;
+import android.app.ActionBar;
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
-import android.widget.MediaController;
import android.widget.VideoView;
import android.support.v4.media.TransportController;
@@ -33,33 +39,266 @@ public class TransportControllerActivity extends Activity {
* TODO: Set the path variable to a streaming video URL or a local media
* file path.
*/
- private VideoView mVideoView;
+ private Content mContent;
private TransportController mTransportController;
+ private MediaController mMediaController;
/**
* Handle media buttons to start/stop video playback. Real implementations
* will probably handle more buttons, like skip and fast-forward.
*/
- public class PlayerControlCallbacks extends TransportController.Callbacks {
+ TransportController.Callbacks mTransportCallbacks = new TransportController.Callbacks() {
public boolean onMediaButtonDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case TransportController.KEYCODE_MEDIA_PLAY:
- mVideoView.start();
+ mMediaPlayerControl.start();
return true;
case TransportController.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_STOP:
- mVideoView.pause();
+ mMediaPlayerControl.pause();
return true;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
- if (mVideoView.isPlaying()) {
- mVideoView.pause();
+ if (mContent.isPlaying()) {
+ mMediaPlayerControl.pause();
} else {
- mVideoView.start();
+ mMediaPlayerControl.start();
}
}
return true;
}
+ };
+
+ /**
+ * Handle actions from on-screen media controls. Most of these are simple re-directs
+ * to the VideoView; some we need to capture to update our state.
+ */
+ MediaController.MediaPlayerControl mMediaPlayerControl
+ = new MediaController.MediaPlayerControl() {
+
+ @Override
+ public void start() {
+ mTransportController.startPlaying();
+ mContent.start();
+ }
+
+ @Override
+ public void pause() {
+ mTransportController.pausePlaying();
+ mContent.pause();
+ }
+
+ @Override
+ public int getDuration() {
+ return mContent.getDuration();
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ return mContent.getCurrentPosition();
+ }
+
+ @Override
+ public void seekTo(int pos) {
+ mContent.seekTo(pos);
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return mContent.isPlaying();
+ }
+
+ @Override
+ public int getBufferPercentage() {
+ return mContent.getBufferPercentage();
+ }
+
+ @Override
+ public boolean canPause() {
+ return mContent.canPause();
+ }
+
+ @Override
+ public boolean canSeekBackward() {
+ return mContent.canSeekBackward();
+ }
+
+ @Override
+ public boolean canSeekForward() {
+ return mContent.canSeekForward();
+ }
+ };
+
+ /**
+ * This is the actual video player. It is the top-level content of
+ * the activity's view hierarchy, going under the status bar and nav
+ * bar areas.
+ */
+ public static class Content extends VideoView implements
+ View.OnSystemUiVisibilityChangeListener, View.OnClickListener,
+ ActionBar.OnMenuVisibilityListener, MediaPlayer.OnPreparedListener,
+ MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
+ Activity mActivity;
+ TransportController mTransportController;
+ MediaController mMediaController;
+ boolean mAddedMenuListener;
+ boolean mMenusOpen;
+ boolean mPaused;
+ boolean mNavVisible;
+ int mLastSystemUiVis;
+
+ Runnable mNavHider = new Runnable() {
+ @Override public void run() {
+ setNavVisibility(false);
+ }
+ };
+
+ Runnable mProgressUpdater = new Runnable() {
+ @Override public void run() {
+ mMediaController.updateProgress();
+ getHandler().postDelayed(this, 1000);
+ }
+ };
+
+ public Content(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnSystemUiVisibilityChangeListener(this);
+ setOnClickListener(this);
+ setOnPreparedListener(this);
+ setOnCompletionListener(this);
+ setOnErrorListener(this);
+ }
+
+ public void init(Activity activity, TransportController transportController,
+ MediaController mediaController) {
+ // This called by the containing activity to supply the surrounding
+ // state of the video player that it will interact with.
+ mActivity = activity;
+ mTransportController = transportController;
+ mMediaController = mediaController;
+ pause();
+ }
+
+ @Override protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mActivity != null) {
+ mAddedMenuListener = true;
+ mActivity.getActionBar().addOnMenuVisibilityListener(this);
+ }
+ }
+
+ @Override protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mAddedMenuListener) {
+ mActivity.getActionBar().removeOnMenuVisibilityListener(this);
+ }
+ mNavVisible = false;
+ }
+
+ @Override public void onSystemUiVisibilityChange(int visibility) {
+ // Detect when we go out of nav-hidden mode, to clear our state
+ // back to having the full UI chrome up. Only do this when
+ // the state is changing and nav is no longer hidden.
+ int diff = mLastSystemUiVis ^ visibility;
+ mLastSystemUiVis = visibility;
+ if ((diff&SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
+ && (visibility&SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
+ setNavVisibility(true);
+ }
+ }
+
+ @Override protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+
+ // When we become visible or invisible, play is paused.
+ pause();
+ }
+
+ @Override public void onClick(View v) {
+ // Clicking anywhere makes the navigation visible.
+ setNavVisibility(true);
+ }
+
+ @Override public void onMenuVisibilityChanged(boolean isVisible) {
+ mMenusOpen = isVisible;
+ setNavVisibility(true);
+ }
+
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mMediaController.setEnabled(true);
+ }
+
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ mTransportController.pausePlaying();
+ pause();
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ mTransportController.pausePlaying();
+ pause();
+ return false;
+ }
+
+ @Override public void start() {
+ super.start();
+ mPaused = false;
+ setKeepScreenOn(true);
+ setNavVisibility(true);
+ mMediaController.refresh();
+ scheduleProgressUpdater();
+ }
+
+ @Override public void pause() {
+ super.pause();
+ mPaused = true;
+ setKeepScreenOn(false);
+ setNavVisibility(true);
+ mMediaController.refresh();
+ scheduleProgressUpdater();
+ }
+
+ void scheduleProgressUpdater() {
+ Handler h = getHandler();
+ if (h != null) {
+ if (mNavVisible && !mPaused) {
+ h.removeCallbacks(mProgressUpdater);
+ h.post(mProgressUpdater);
+ } else {
+ h.removeCallbacks(mProgressUpdater);
+ }
+ }
+ }
+
+ void setNavVisibility(boolean visible) {
+ int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ if (!visible) {
+ newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN
+ | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ }
+
+ // If we are now visible, schedule a timer for us to go invisible.
+ if (visible) {
+ Handler h = getHandler();
+ if (h != null) {
+ h.removeCallbacks(mNavHider);
+ if (!mMenusOpen && !mPaused) {
+ // If the menus are open or play is paused, we will not auto-hide.
+ h.postDelayed(mNavHider, 3000);
+ }
+ }
+ }
+
+ // Set the new desired visibility.
+ setSystemUiVisibility(newVis);
+ mNavVisible = visible;
+ mMediaController.setVisibility(visible ? VISIBLE : INVISIBLE);
+ scheduleProgressUpdater();
+ }
}
@Override
@@ -68,27 +307,31 @@ public class TransportControllerActivity extends Activity {
setContentView(R.layout.videoview);
// Find the video player in our UI.
- mVideoView = (VideoView) findViewById(R.id.surface_view);
+ mContent = (Content) findViewById(R.id.content);
- // Create transport controller to control video; use the standard
- // control callbacks that knows how to talk to a MediaPlayerControl.
- mTransportController = new TransportController(this, new PlayerControlCallbacks());
+ // Create and initialize the media control UI.
+ mMediaController = (MediaController) findViewById(R.id.media_controller);
+ mMediaController.setMediaPlayer(mMediaPlayerControl);
+
+ // Create transport controller to control video, giving the callback
+ // interface to receive actions from.
+ mTransportController = new TransportController(this, mTransportCallbacks);
// We're just playing a built-in demo video.
- mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() +
+ mContent.init(this, mTransportController, mMediaController);
+ mContent.setVideoURI(Uri.parse("android.resource://" + getPackageName() +
"/" + R.raw.videoviewdemo));
- mVideoView.setMediaController(new MediaController(this));
- mVideoView.requestFocus();
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (super.dispatchKeyEvent(event)) {
+ // We first dispatch keys to the transport controller -- we want it
+ // to get to consume any media keys rather than letting whoever has focus
+ // in the view hierarchy to potentially eat it.
+ if (mTransportController.dispatchKeyEvent(event)) {
return true;
}
- // If the UI didn't handle the key, give the transport controller
- // a crack at it.
- return mTransportController.dispatchKeyEvent(event);
+ return super.dispatchKeyEvent(event);
}
}