public class TransportMediator
extends TransportController
| java.lang.Object | ||
| android.support.v4.media.TransportController | ||
| android.support.v4.media.TransportMediator | ||
助手实现媒体传输控制(播放,暂停,跳过和其他媒体操作)。 照顾重要事件和高级功能,如RemoteControlClient 。 该课程旨在作为交通控制(无论是屏幕控制,硬件按钮,遥控器)还是实际玩家之间的中介。 玩家由一个TransportPerformer代表,必须提供给该课程。 希望控制和显示播放器状态的屏幕控件应通过调用TransportController界面来完成。
这是一个简单但相当完整的围绕此课程构建的视频播放器示例。 请注意,此处使用的MediaController类不是标准Android框架中包含的类,而是自定义实现。 真正的应用程序通常会实现自己的传输控制,或者您可以将实现从Support4Demos中复制出来。
import android.support.v4.media.TransportMediator;
import android.support.v4.media.TransportPerformer;
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.VideoView;
public class TransportControllerActivity extends Activity {
/**
* TODO: Set the path variable to a streaming video URL or a local media
* file path.
*/
private Content mContent;
private TransportMediator mTransportMediator;
private MediaController mMediaController;
/**
* 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.
*/
TransportPerformer mTransportPerformer = new TransportPerformer() {
@Override public void onStart() {
mContent.start();
}
@Override public void onStop() {
mContent.pause();
}
@Override public void onPause() {
mContent.pause();
}
@Override public long onGetDuration() {
return mContent.getDuration();
}
@Override public long onGetCurrentPosition() {
return mContent.getCurrentPosition();
}
@Override public void onSeekTo(long pos) {
mContent.seekTo((int)pos);
}
@Override public boolean onIsPlaying() {
return mContent.isPlaying();
}
@Override public int onGetBufferPercentage() {
return mContent.getBufferPercentage();
}
@Override public int onGetTransportControlFlags() {
int flags = TransportMediator.FLAG_KEY_MEDIA_PLAY
| TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE
| TransportMediator.FLAG_KEY_MEDIA_STOP;
if (mContent.canPause()) {
flags |= TransportMediator.FLAG_KEY_MEDIA_PAUSE;
}
if (mContent.canSeekBackward()) {
flags |= TransportMediator.FLAG_KEY_MEDIA_REWIND;
}
if (mContent.canSeekForward()) {
flags |= TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD;
}
return flags;
}
};
/**
* 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;
TransportMediator mTransportMediator;
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, TransportMediator transportMediator,
MediaController mediaController) {
// This called by the containing activity to supply the surrounding
// state of the video player that it will interact with.
mActivity = activity;
mTransportMediator = transportMediator;
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) {
mTransportMediator.pausePlaying();
pause();
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mTransportMediator.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
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.videoview);
// Find the video player in our UI.
mContent = (Content) findViewById(R.id.content);
// Create transport controller to control video, giving the callback
// interface to receive actions from.
mTransportMediator = new TransportMediator(this, mTransportPerformer);
// Create and initialize the media control UI.
mMediaController = (MediaController) findViewById(R.id.media_controller);
mMediaController.setMediaPlayer(mTransportMediator);
// We're just playing a built-in demo video.
mContent.init(this, mTransportMediator, mMediaController);
mContent.setVideoURI(Uri.parse("android.resource://" + getPackageName() +
"/" + R.raw.videoviewdemo));
}
@Override
public boolean dispatchKeyEvent(KeyEvent 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 (mTransportMediator.dispatchKeyEvent(event)) {
return true;
}
return super.dispatchKeyEvent(event);
}
}
常量(Constants) |
|
|---|---|
int |
FLAG_KEY_MEDIA_FAST_FORWARD {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_FAST_FORWARD RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD的同义词 |
int |
FLAG_KEY_MEDIA_NEXT {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_NEXT RemoteControlClient.FLAG_KEY_MEDIA_NEXT的同义词 |
int |
FLAG_KEY_MEDIA_PAUSE {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PAUSE RemoteControlClient.FLAG_KEY_MEDIA_PAUSE的同义词 |
int |
FLAG_KEY_MEDIA_PLAY {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY RemoteControlClient.FLAG_KEY_MEDIA_PLAY的同义词 |
int |
FLAG_KEY_MEDIA_PLAY_PAUSE {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY_PAUSE RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE的同义词 |
int |
FLAG_KEY_MEDIA_PREVIOUS {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PREVIOUS RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS的同义词 |
int |
FLAG_KEY_MEDIA_REWIND {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_REWIND RemoteControlClient.FLAG_KEY_MEDIA_REWIND的同义词 |
int |
FLAG_KEY_MEDIA_STOP {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_STOP RemoteControlClient.FLAG_KEY_MEDIA_STOP的同义词 |
int |
KEYCODE_MEDIA_PAUSE |
int |
KEYCODE_MEDIA_PLAY |
int |
KEYCODE_MEDIA_RECORD |
Public constructors |
|
|---|---|
TransportMediator(Activity activity, TransportPerformer callbacks) |
|
TransportMediator(View view, TransportPerformer callbacks) |
|
公共方法(Public methods) |
|
|---|---|
void |
destroy() 可选择在不再使用TransportController时调用。 |
boolean |
dispatchKeyEvent(KeyEvent event) 必须从 |
int |
getBufferPercentage() 以百分比(0-100)检索媒体流已缓冲到本地设备的金额。 |
long |
getCurrentPosition() 以毫秒为单位检索媒体流中的当前播放位置。 |
long |
getDuration() 检索媒体流的总持续时间,以毫秒为单位。 |
Object |
getRemoteControlClient() 返回与此运输相关的 |
int |
getTransportControlFlags() 检索此传输支持的媒体传输控制按钮的标志。 |
boolean |
isPlaying() 返回玩家是否正在播放其流。 |
void |
pausePlaying() 将控制器移至暂停状态。 |
void |
refreshState() |
void |
registerStateListener(TransportStateListener listener) 开始监听播放状态的变化。 |
void |
seekTo(long pos) 移动到媒体流中的新位置。 |
void |
startPlaying() 将控制器移到播放状态。 |
void |
stopPlaying() 将控制器移至停止状态。 |
void |
unregisterStateListener(TransportStateListener listener) 停止收听播放状态的变化。 |
继承方法(Inherited methods) |
|
|---|---|
android.support.v4.media.TransportController
|
|
java.lang.Object
|
|
int FLAG_KEY_MEDIA_FAST_FORWARD
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_FAST_FORWARD RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD的同义词
常量值:64(0x00000040)
int FLAG_KEY_MEDIA_NEXT
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_NEXT RemoteControlClient.FLAG_KEY_MEDIA_NEXT的同义词
常量值:128(0x00000080)
int FLAG_KEY_MEDIA_PAUSE
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PAUSE RemoteControlClient.FLAG_KEY_MEDIA_PAUSE的同义词
常量值:16(0x00000010)
int FLAG_KEY_MEDIA_PLAY
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY RemoteControlClient.FLAG_KEY_MEDIA_PLAY的同义词
常量值:4(0x00000004)
int FLAG_KEY_MEDIA_PLAY_PAUSE
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY_PAUSE RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE的同义词
常量值:8(0x00000008)
int FLAG_KEY_MEDIA_PREVIOUS
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PREVIOUS RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS的同义词
常数值:1(0x00000001)
int FLAG_KEY_MEDIA_REWIND
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_REWIND RemoteControlClient.FLAG_KEY_MEDIA_REWIND的同义词
常量值:2(0x00000002)
int FLAG_KEY_MEDIA_STOP
{@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_STOP RemoteControlClient.FLAG_KEY_MEDIA_STOP的同义词
常量值:32(0x00000020)
int KEYCODE_MEDIA_RECORD
同义词为 KeyEvent.KEYCODE_MEDIA_RECORD
常量值:130(0x00000082)
TransportMediator (Activity activity, TransportPerformer callbacks)
| 参数(Parameters) | |
|---|---|
activity |
Activity
|
callbacks |
TransportPerformer
|
TransportMediator (View view, TransportPerformer callbacks)
| 参数(Parameters) | |
|---|---|
view |
View
|
callbacks |
TransportPerformer
|
void destroy ()
可选择在不再使用TransportController时调用。 当您的活动/视图从窗口中分离出来时,它的资源也会自动清除,所以您通常不需要明确地调用它。
boolean dispatchKeyEvent (KeyEvent event)
必须致电Activity.dispatchKeyEvent为交通工具提供拦截媒体密钥的机会。 任何此类密钥将显示在TransportPerformer 。
| 返回(Returns) | |
|---|---|
boolean |
|
int getBufferPercentage ()
以百分比(0-100)检索媒体流已缓冲到本地设备的金额。 如果流始终是本地的,则返回100。
| 返回(Returns) | |
|---|---|
int |
|
long getCurrentPosition ()
以毫秒为单位检索媒体流中的当前播放位置。
| 返回(Returns) | |
|---|---|
long |
|
long getDuration ()
检索媒体流的总持续时间,以毫秒为单位。
| 返回(Returns) | |
|---|---|
long |
|
Object getRemoteControlClient ()
返回与此运输相关的RemoteControlClient 。 这会返回一个通用对象,因为在ICE_CREAM_SANDWICH之前RemoteControlClient不可ICE_CREAM_SANDWICH 。 此外,该类不会在其实现中使用RemoteControlClient,直到JELLY_BEAN_MR2 。 您应该始终在此处检查null,如果没有给出RemoteControlClient,则不执行任何操作; 这样您就不必担心当前的平台API版本。
请注意,这个类别拥有RemoteControlClient.OnGetPlaybackPositionListener和RemoteControlClient.OnPlaybackPositionUpdateListener回调; 你将分别通过TransportPerformer.onGetCurrentPosition和TransportPerformer.onSeekTo与这些进行交互。
| 返回(Returns) | |
|---|---|
Object |
|
int getTransportControlFlags ()
检索此传输支持的媒体传输控制按钮的标志。 结果是下列标志的组合: FLAG_KEY_MEDIA_PREVIOUS , FLAG_KEY_MEDIA_REWIND , FLAG_KEY_MEDIA_PLAY , FLAG_KEY_MEDIA_PLAY_PAUSE , FLAG_KEY_MEDIA_PAUSE , FLAG_KEY_MEDIA_STOP , FLAG_KEY_MEDIA_FAST_FORWARD , FLAG_KEY_MEDIA_NEXT
| 返回(Returns) | |
|---|---|
int |
|
boolean isPlaying ()
返回玩家是否正在播放其流。
| 返回(Returns) | |
|---|---|
boolean |
|
void pausePlaying ()
将控制器移至暂停状态。 这会更新远程控制客户端以指示它已暂停,但保持音频焦点。
void refreshState ()
void registerStateListener (TransportStateListener listener)
开始监听播放状态的变化。
| 参数(Parameters) | |
|---|---|
listener |
TransportStateListener
|
void seekTo (long pos)
移动到媒体流中的新位置。
| 参数(Parameters) | |
|---|---|
pos |
long: Position to move to, in milliseconds. |
void startPlaying ()
将控制器移到播放状态。 这会更新远程控制客户端以指示它正在播放,并为应用程序占用音频焦点。
void stopPlaying ()
将控制器移至停止状态。 这会更新远程控制客户端以指示它已停止,并从应用程序中删除音频焦点。
void unregisterStateListener (TransportStateListener listener)
停止收听播放状态的变化。
| 参数(Parameters) | |
|---|---|
listener |
TransportStateListener
|