我使用mediaplayer.xml播放视频文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/MainView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#4d4d4d"
android:gravity="center"
android:keepScreenOn="true"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
以下使用SurfaceView和MediaPlayer的MediaPlayerActivity类 在纵向模式下播放视频时,视频似乎拉伸了一个。我想在垂直中心播放视频,不应占用全屏,然后在横向模式下应以全屏模式播放。
public class MediaPlayerActivity extends Activity implements OnCompletionListener,
OnErrorListener, OnInfoListener, OnBufferingUpdateListener,
OnPreparedListener, OnSeekCompleteListener, SurfaceHolder.Callback,
MediaController.MediaPlayerControl {
private MediaController controller;
Display currentDisplay;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer;
int videoWidth = 0;
int videoHeight = 0;
boolean readyToPlay = false;
private String streamingVideoUrl;
private ProgressDialog dialog;
public final String TAG = "VIDEO_PLAYER";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"Media player activity called ");
setContentView(R.layout.mediaplayer);
if(getIntent() != null ){
streamingVideoUrl = getIntent().getStringExtra("stream_url");
}
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setOnClickListener(surViewClickListener);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/*setVideoSize();*/
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//Log.d(TAG,"Returned by getDatasource :"+getDataSource(streamingVideoUrl));
mediaPlayer.setDataSource(streamingVideoUrl);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
currentDisplay = getWindowManager().getDefaultDisplay();
controller = new MediaController(this);
dialog = new ProgressDialog(this);
//dialog.setMessage("Preparing File to Streaming");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setCanceledOnTouchOutside(false);
if(this!= null && !this.isFinishing()){
dialog.show();
}
handler.postDelayed(r, 100);
}
/*private void setVideoSize() {
try {
// // Get the dimensions of the video
int videoWidth = mediaPlayer.getVideoWidth();
int videoHeight = mediaPlayer.getVideoHeight();
float videoProportion = (float) videoWidth / (float) videoHeight;
// Get the width of the screen
int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
float screenProportion = (float) screenWidth / (float) screenHeight;
// Get the SurfaceView layout parameters
android.view.ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
if (videoProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / videoProportion);
} else {
lp.width = (int) (videoProportion * (float) screenHeight);
lp.height = screenHeight;
}
// Commit the layout parameters
surfaceView.setLayoutParams(lp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
/*//coded by Karthikeyan V
//converting url to byte
private String getDataSource(String path) throws IOException {
Log.d(TAG,"getDataSource called");
if (!URLUtil.isNetworkUrl(path)) {
return path;
} else {
URL url = new URL(path);
URLConnection cn = url.openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null)
throw new RuntimeException("stream is null");
File temp = File.createTempFile("mediaplayertmp", "dat");
temp.deleteOnExit();
String tempPath = temp.getAbsolutePath();
FileOutputStream out = new FileOutputStream(temp);
byte buf[] = new byte[128];
do {
int numread = stream.read(buf);
if (numread <= 0)
break;
out.write(buf, 0, numread);
} while (true);
try {
stream.close();
} catch (IOException ex) {
Log.e(TAG, "error: " + ex.getMessage(), ex);
}
Log.d(TAG,"temp path :"+tempPath);
return tempPath;
}
}*/
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public int getCurrentPosition() {
if(mediaPlayer !=null)
return mediaPlayer.getCurrentPosition();
else
return 0;
}
@Override
public int getDuration() {
return mediaPlayer.getDuration();
}
@Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
@Override
public void pause() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
}
@Override
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
@Override
public void start() {
mediaPlayer.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceChanged Called");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceCreated Called");
mediaPlayer.setDisplay(holder);
try {
mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow IllegalStateException " + e.getMessage());
finish();
}
if(Constants.DEBUG)
Log.d(TAG, "Media Flow MediaPlayer Preparing");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceDestroyed Called");
}
@Override
public void onSeekComplete(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onSeekComplete Called");
}
@Override
public void onPrepared(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onPrepared Called");
// dismissProgressLoading();
controller.setMediaPlayer(this);
controller.setAnchorView(this.findViewById(R.id.MainView));
controller.setEnabled(true);
controller.show();
mp.start();
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow MediaPlayer Buffering: " + percent + "%");
dismissProgressLoading();
}
@Override
public boolean onInfo(MediaPlayer mp, int whatInfo, int extra) {
//
dismissProgressLoading();
if(Constants.DEBUG)
{
if (whatInfo == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow Media Info, Media Info Bad Interleaving " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow Media Info, Media Info Not Seekable " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_UNKNOWN) {
Log.v(TAG, "Media Flow Media Info, Media Info Unknown " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Log.v(TAG, "Media Flow MediaInfo, Media Info Video Track Lagging " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
Log.v(TAG, "Media Flow MediaInfo, Media Info Metadata Update " + extra);
}
}
return false;
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
dismissProgressLoading();
StringBuilder sb = new StringBuilder();
sb.append("Media Player Error: ");
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
sb.append("Not Valid for Progressive Playback");
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
sb.append("Server Died");
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
sb.append("Media Error Unknown");
break;
default:
sb.append(" Non standard (");
sb.append(what);
sb.append(")");
}
//sb.append(" (" + what + ") ");
sb.append(extra);
showErrorDialog("Cannot play video", sb.toString());
return true;
}
void dismissProgressLoading() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
@Override
public void onCompletion(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onCompletion Called");
dismissProgressLoading();
onBackPressed();
}
@Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
final Runnable r = new Runnable() {
public void run() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()
&& mediaPlayer.getCurrentPosition() > 0) {
if(Constants.DEBUG)
Log.d(TAG, "isPlaying : " + mediaPlayer.isPlaying());
if(Constants.DEBUG)
Log.d(TAG,
"currentPosition : "
+ mediaPlayer.getCurrentPosition());
handler.sendEmptyMessage(0);
} else {
handler.postDelayed(this, 100);
}
}
}
};
Handler handler = new Handler() {
public void handleMessage(Message msg) {
dismissProgressLoading();
}
};
@Override
protected void onResume() {
if(Constants.SHOULD_FINISH_APPLICATION)
finish();
super.onResume();
}
@Override
protected void onRestart() {
super.onRestart();
}
protected void onPause() {
super.onPause();
pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
dismissProgressLoading();
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
if(controller !=null)
{
controller.hide();
}
}
OnClickListener surViewClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (controller != null) {
if (controller.isShowing()) {
controller.hide();
} else {
controller.show();
}
}
}
};
@SuppressWarnings("deprecation")
void showErrorDialog(String title, String message) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
// Setting Dialog Title
alertDialog.setTitle(title);
// Setting Dialog Message
alertDialog.setMessage(message);
// Setting Icon to Dialog
alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
// Setting OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog closed
dialog.dismiss();
finish();
}
});
// Showing Alert Message
if(this!= null && !this.isFinishing()){
alertDialog.show();
}
}
}
答案 0 :(得分:3)
handleAspectRatio() {
int surfaceView_Width = surfaceView.getWidth();
int surfaceView_Height = surfaceView.getHeight();
float video_Width = mediaPlayer.getVideoWidth();
float video_Height = mediaPlayer.getVideoHeight();
float ratio_width = surfaceView_Width/video_Width;
float ratio_height = surfaceView_Height/video_Height;
float aspectratio = video_Width/video_Height;
LayoutParams layoutParams = surfaceView.getLayoutParams();
if (ratio_width > ratio_height){
layoutParams.width = (int) (surfaceView_Height * aspectratio);
layoutParams.height = surfaceView_Height;
}else{
layoutParams.width = surfaceView_Width;
layoutParams.height = (int) (surfaceView_Width / aspectratio);
}
surfaceView.setLayoutParams(layoutParams);
}
在调用
之前调用上面的函数mediaPlayer.start();
答案 1 :(得分:2)
I met the same problem,after i look into VideoView
source code in API 23,i found the good method,here is my solution,we can create a custom SurfaceView
and override onMeasure()
,then here you go,use VideoSurfaceView
to play the video.
public class VideoSurfaceView extends SurfaceView implements MediaPlayer.OnVideoSizeChangedListener {
private int mVideoWidth;
private int mVideoHeight;
public VideoSurfaceView(Context context) {
super(context);
}
public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Set video size.
*
* @see MediaPlayer#getVideoWidth()
* @see MediaPlayer#getVideoHeight()
*/
public void setVideoSize(int videoWidth, int videoHeight) {
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
setMeasuredDimension(width, height);
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
getHolder().setFixedSize(mVideoWidth, mVideoHeight);
requestLayout();
}
}
}