众所周知一个媒体播放器新建的几个步骤:
Mediaplayer mp = new MediaPlayer(0 mp.setDatasource(xxx); mp.setDispalyer(xxx); mp.setAudioStreamType(xxx); mp.prepareAsync(); mp.start
这个和activity该如何绑定呢?本文则是通过图库分析,来说明此中明细。
打开图库显得的是一个名字叫MovieActivity的Actiivity,具有activity的的生命周期,而媒体的操作是如何和他们关联起来呢,详见下图(图片长,上传的时候出现了背景黑色的情况,不知道为什么,此处分开贴图,真实图片上传资源那边,0积分下载):
资源下载地址 :http://download.csdn.net/detail/loovejava/6272059
从代码看到的和媒体关联的就这这几个生命周期的时候,onCreate() , onResume() ,onPause() ,onDestory()。
onPause在android媒体——图库pause时与服务端断开连接 中有讲述。
onCreate只是进行了初始化,无其他特殊操作
onDestory中则是停止了框架层mediaplayer的播放,并且对其进行状态反初始化的操作。
主要是在两个onResume和onKeyDown方法:
简明的说下,onResume是新建了一个媒体播放器并设置监听。
onKeyDown则是通过监听点击时间,来控制媒体的播放和暂停。
======================================= 下面附上关键代码=========================================================
1、onResume初始化媒体:
packageappsGallery2srccomandroidgallery3dappMovieActivity.java
public void onResume() { mPlayer.onResume(); super.onResume(); }
packageappsGallery2srccomandroidgallery3dappMoviePlayer.java
public void onResume() { if (mHasPaused) { mVideoView.seekTo(mVideoPosition); mVideoView.resume(); // If we have slept for too long, pause the play if (System.currentTimeMillis() > mResumeableTime) { pauseVideo(); } } mHandler.post(mProgressChecker); }
frameworkasecorejavaandroidwidgetViewView.java
public void resume() { openVideo(); } ... ... private void openVideo() { if (mUri == null || mSurfaceHolder == null) { // not ready for playback just yet, will try again later return; } // Tell the music playback service to pause // TODO: these constants need to be published somewhere in the framework. Intent i = new Intent("com.android.music.musicservicecommand"); i.putExtra("command", "pause"); mContext.sendBroadcast(i); // we shouldn't clear the target state, because somebody might have // called start() previously release(false); try { mMediaPlayer = new MediaPlayer(); if (mAudioSession != 0) { mMediaPlayer.setAudioSessionId(mAudioSession); } else { mAudioSession = mMediaPlayer.getAudioSessionId(); } mMediaPlayer.setOnPreparedListener(mPreparedListener); mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); mMediaPlayer.setOnCompletionListener(mCompletionListener); mMediaPlayer.setOnErrorListener(mErrorListener); mMediaPlayer.setOnInfoListener(mOnInfoListener); mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); mCurrentBufferPercentage = 0; mMediaPlayer.setDataSource(mContext, mUri, mHeaders); mMediaPlayer.setDisplay(mSurfaceHolder); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mMediaPlayer.setScreenOnWhilePlaying(true); mMediaPlayer.prepareAsync(); // we don't set the target state here either, but preserve the // target state that was there before. mCurrentState = STATE_PREPARING; attachMediaController(); } catch (IOException ex) { Log.w(TAG, "Unable to open content: " + mUri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); return; } catch (IllegalArgumentException ex) { Log.w(TAG, "Unable to open content: " + mUri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); return; } }
致此已经初始化完毕
2、onKeyDown的如何操控状态改变呢?
packageappsGallery2srccomandroidgallery3dappMoviePlayer.java
private void playVideo() { mVideoView.start(); mController.showPlaying(); setProgress(); } private void pauseVideo() { mVideoView.pause(); mController.showPaused(); } ... ... public boolean onKeyDown(int keyCode, KeyEvent event) { // Some headsets will fire off 7-10 events on a single click if (event.getRepeatCount() > 0) { return isMediaKey(keyCode); } switch (keyCode) { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: if (mVideoView.isPlaying()) { pauseVideo(); } else { playVideo(); } return true; case KEYCODE_MEDIA_PAUSE: if (mVideoView.isPlaying()) { pauseVideo(); } return true; case KEYCODE_MEDIA_PLAY: if (!mVideoView.isPlaying()) { playVideo(); } return true; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: case KeyEvent.KEYCODE_MEDIA_NEXT: // TODO: Handle next / previous accordingly, for now we're // just consuming the events. return true; } return false; }
frameworkasecorejavaandroidwidgetViewView.java
@Override public void start() { if (isInPlaybackState()) { mMediaPlayer.start(); mCurrentState = STATE_PLAYING; } mTargetState = STATE_PLAYING; } @Override public void pause() { if (isInPlaybackState()) { if (mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); mCurrentState = STATE_PAUSED; } } mTargetState = STATE_PAUSED; }
至此已经把想操作媒体的意愿发送至mediaPlayer,mediaplayer会进行先关的处理,如何处理,后面播客会详细的讲述。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
看了本文一定有一个疑问,为什么moviePlayer为什么不直接调用mediaplayer的方法呢,为什么中间要隔着一个“第三者”呢?
从上图可以看出videoView继承了SurfaceView,实现了MediaPlayerControl接口,还依赖MediaPlayer
显而易见,我们看到了VideoView就是把媒体,媒体控制和显示的组合体,也可以理解成一个调度类。
我们写如果不使用VideoView的话,自己还得去实现媒体控制的相关操作和显示的相关操作。
here over.