由于项目中中需要用到在线视频播放功能,而Android自带的mediaplayer类支持的格式太少,而vitamio框架性能强大支持的格式众多,支持在线播放。
使用vitamio框架的MediaPlayer这个类进行播放网络视频,在使用的过程中遇到一些问题,MediaPlayer的setOnInfoListener函数用来注册信息监听器,主要监听的是缓冲开始,缓冲结束,下载速度发生变化之类的事件,我遇到的问题是视频播放或者拖动了seekbar后开始缓冲,结果是一直缓冲到视频结束才会监听到缓冲结束事件,在这期间注册的setOnBufferingUpdateListener监听器监听到的数据也是无效的,甚至还出现123这样的百分比,上网搜索了一两个小时没有什么收获,于是只有看vitamio框架的VideoView类,他继承了surfaceview,实际上就是对surfaceview和MediaPlayer进行了封装,用它来进行播放,缓冲的数据是正常。于是开始阅读源码,发现他跟我之前写的有一个地方不一样,VideoView在准备完成之后进行设置surfaceview的布局,没有开始播放视频。而我的是设置完后开始播放视频,于是我试着注释掉start();缓冲终于正常了。
缓冲有问题的代码
package io.vov.vitamio.demo;
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import io.vov.vitamio.LibsChecker;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener;
import io.vov.vitamio.MediaPlayer.OnCompletionListener;
import io.vov.vitamio.MediaPlayer.OnInfoListener;
import io.vov.vitamio.MediaPlayer.OnPreparedListener;
import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.MediaController.MediaPlayerControl;
public class MediaPlayerDemo_Video extends Activity implements OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {
private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private String path;
private Bundle extras;
int downloadSize=0;
private static final String MEDIA = "media";
private static final int LOCAL_AUDIO = 1;
private static final int STREAM_AUDIO = 2;
private static final int RESOURCES_AUDIO = 3;
private static final int LOCAL_VIDEO = 4;
private static final int STREAM_VIDEO = 5;
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;
MediaController mc;
ProgressBar pb;
TextView download_rate,rate;
/**
*
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (!LibsChecker.checkVitamioLibs(this))
return;
setContentView(R.layout.mediaplayer_2);
mPreview = (SurfaceView) findViewById(R.id.surface);
mPreview.requestFocus();
holder = mPreview.getHolder();
holder.addCallback(this);
holder.setFormat(PixelFormat.RGBA_8888);
extras = getIntent().getExtras();
mc=new MediaController(this);
download_rate=(TextView)findViewById(R.id.rate);
rate=(TextView)findViewById(R.id.percent);
pb=(ProgressBar) findViewById(R.id.progressbar);
}
private void playVideo(Integer Media) {
doCleanUp();
try {
switch (Media) {
case LOCAL_VIDEO:
case STREAM_VIDEO:
path = "http://211.144.85.251/tangbohu.mp4";
path="http://www.modrails.com/videos/passenger_nginx.mov";
mMediaPlayer = new MediaPlayer(this);
mMediaPlayer.setDataSource(this,Uri.parse(path));
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mMediaPlayer.setVideoQuality(MediaPlayer.VIDEOQUALITY_LOW);
mMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.i(TAG,"已经缓冲:"+percent+"%");
rate.setText(percent+"%");
}
});
mMediaPlayer.setOnInfoListener(new OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch(what)
{
case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:
Log.i(TAG,"下载的速率:"+extra);
download_rate.setText(extra+"kb/s");
downloadSize+=extra;
return true;
case MediaPlayer.MEDIA_INFO_BUFFERING_END:
Log.i(TAG,"缓冲结束");
pb.setVisibility(ViewGroup.GONE);
rate.setVisibility(ViewGroup.GONE);
download_rate.setVisibility(ViewGroup.GONE);
mMediaPlayer.start();
return true;
case MediaPlayer.MEDIA_INFO_BUFFERING_START:
Log.i(TAG,"缓冲开始");
downloadSize=0;
if(mMediaPlayer.isPlaying())
mMediaPlayer.pause();
pb.setVisibility(ViewGroup.VISIBLE);
rate.setVisibility(ViewGroup.VISIBLE);
download_rate.setVisibility(ViewGroup.VISIBLE);
return true;
}
return false;
}
});
mc.setAnchorView(mPreview);
mc.setMediaPlayer(new MediaPlayerControl() {
@Override
public void start() {
if(mMediaPlayer.isPlaying())
mMediaPlayer.stop();
mMediaPlayer.start();
}
@Override
public void seekTo(long pos) {
mMediaPlayer.seekTo(pos);
}
@Override
public void pause() {
mMediaPlayer.pause();
}
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
@Override
public long getDuration() {
return mMediaPlayer.getDuration();
}
@Override
public long getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
@Override
public int getBufferPercentage() {
return mMediaPlayer.getBufferProgress();
}
});
} }catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}
public void onCompletion(MediaPlayer arg0) {
Log.d(TAG, "onCompletion called");
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
return;
}
Log.i(TAG,"width:"+width+"height:"+height);
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void onPrepared(MediaPlayer mediaplayer) {
Log.i(TAG, "onPrepared called");
mIsVideoReadyToBePlayed = true;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
Log.d(TAG, "surfaceChanged called");
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(TAG, "surfaceDestroyed called");
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated called");
playVideo(extras.getInt(MEDIA));
mPreview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mc.show();
}
});
}
@Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}
private void releaseMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
private void doCleanUp() {
mVideoWidth = 0;
mVideoHeight = 0;
mIsVideoReadyToBePlayed = false;
mIsVideoSizeKnown = false;
}
private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback");
holder.setFixedSize(mVideoWidth, mVideoHeight);
mMediaPlayer.start();
}
}
缓冲正常的代码
package io.vov.vitamio.demo;
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import io.vov.vitamio.LibsChecker;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener;
import io.vov.vitamio.MediaPlayer.OnCompletionListener;
import io.vov.vitamio.MediaPlayer.OnInfoListener;
import io.vov.vitamio.MediaPlayer.OnPreparedListener;
import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.MediaController.MediaPlayerControl;
public class MediaPlayerDemo_Video extends Activity implements OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {
private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private String path;
private Bundle extras;
int downloadSize=0;
private static final String MEDIA = "media";
private static final int LOCAL_AUDIO = 1;
private static final int STREAM_AUDIO = 2;
private static final int RESOURCES_AUDIO = 3;
private static final int LOCAL_VIDEO = 4;
private static final int STREAM_VIDEO = 5;
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;
MediaController mc;
ProgressBar pb;
TextView download_rate,rate;
/**
*
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (!LibsChecker.checkVitamioLibs(this))
return;
setContentView(R.layout.mediaplayer_2);
mPreview = (SurfaceView) findViewById(R.id.surface);
mPreview.requestFocus();
holder = mPreview.getHolder();
holder.addCallback(this);
holder.setFormat(PixelFormat.RGBA_8888);
extras = getIntent().getExtras();
mc=new MediaController(this);
download_rate=(TextView)findViewById(R.id.rate);
rate=(TextView)findViewById(R.id.percent);
pb=(ProgressBar) findViewById(R.id.progressbar);
}
private void playVideo(Integer Media) {
doCleanUp();
try {
switch (Media) {
case LOCAL_VIDEO:
case STREAM_VIDEO:
path = "http://211.144.85.251/tangbohu.mp4";
path="http://www.modrails.com/videos/passenger_nginx.mov";
mMediaPlayer = new MediaPlayer(this);
mMediaPlayer.setDataSource(this,Uri.parse(path));
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mMediaPlayer.setVideoQuality(MediaPlayer.VIDEOQUALITY_LOW);
mMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.i(TAG,"已经缓冲:"+percent+"%");
rate.setText(percent+"%");
}
});
mMediaPlayer.setOnInfoListener(new OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch(what)
{
case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:
Log.i(TAG,"下载的速率:"+extra);
download_rate.setText(extra+"kb/s");
downloadSize+=extra;
return true;
case MediaPlayer.MEDIA_INFO_BUFFERING_END:
Log.i(TAG,"缓冲结束");
pb.setVisibility(ViewGroup.GONE);
rate.setVisibility(ViewGroup.GONE);
download_rate.setVisibility(ViewGroup.GONE);
mMediaPlayer.start();
return true;
case MediaPlayer.MEDIA_INFO_BUFFERING_START:
Log.i(TAG,"缓冲开始");
downloadSize=0;
if(mMediaPlayer.isPlaying())
mMediaPlayer.pause();
pb.setVisibility(ViewGroup.VISIBLE);
rate.setVisibility(ViewGroup.VISIBLE);
download_rate.setVisibility(ViewGroup.VISIBLE);
return true;
}
return false;
}
});
mc.setAnchorView(mPreview);
mc.setMediaPlayer(new MediaPlayerControl() {
@Override
public void start() {
if(mMediaPlayer.isPlaying())
mMediaPlayer.stop();
mMediaPlayer.start();
}
@Override
public void seekTo(long pos) {
mMediaPlayer.seekTo(pos);
}
@Override
public void pause() {
mMediaPlayer.pause();
}
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
@Override
public long getDuration() {
return mMediaPlayer.getDuration();
}
@Override
public long getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
@Override
public int getBufferPercentage() {
return mMediaPlayer.getBufferProgress();
}
});
} }catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}
public void onCompletion(MediaPlayer arg0) {
Log.d(TAG, "onCompletion called");
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
return;
}
Log.i(TAG,"width:"+width+"height:"+height);
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void onPrepared(MediaPlayer mediaplayer) {
Log.i(TAG, "onPrepared called");
mIsVideoReadyToBePlayed = true;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
Log.d(TAG, "surfaceChanged called");
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(TAG, "surfaceDestroyed called");
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated called");
playVideo(extras.getInt(MEDIA));
mPreview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mc.show();
}
});
}
@Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}
private void releaseMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
private void doCleanUp() {
mVideoWidth = 0;
mVideoHeight = 0;
mIsVideoReadyToBePlayed = false;
mIsVideoSizeKnown = false;
}
private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback");
holder.setFixedSize(mVideoWidth, mVideoHeight);
}
}