使用MediaPlayer来播放视频

作者:温尚书,华清远见嵌入式学院讲师。

在上一篇文章中,我们讨论了如何在android中播放视频,并且讲解了VideoView的使用。本篇文章将继续上篇文章的主题,来学习如何使用MediaPlayer来播放视频。

对于MediaPlayer,要熟练掌握它的用法,一定要熟悉下面这张MediaPlayer的方法调用和状态转换图。

这张MediaPLayer状态图看起来很复杂,但实际上,只要理解了它的基本过程,就不会那么难了。我们可以结合我们播放视频的过程来了解,我们如果需要播放一个视频,大致的流程是:创建播放器对象?设置需要播放的视频的来源?对视频进行解码等准备工作?开始播放?(暂停?重启)?停止播放。对应这些流程,在MediaPlayer中都定义了相关的方法,而且,在调用这些方法后,MediaPlayer可以进入不同的状态。这些方法和状态都很好理解,读者可以参照上图来了解。另外,因为在设置播放的视频的视频数据源之后,它需要对其进行解码(调用prepare()方法),这是一个比较耗时的操作,所以为了避免应用程序阻止在这里,可以使用它的prepareAsync()方法配合OnPreparedListener监听器来让其异步操作。注意,只有MediaPlayer的准备工作做完后,才能开始播放。

MediaPlayer本身不能显示视频内容,它只能控制视频的播放。如果要使用MediaPlayer来播放视频,还需要配合SurfaceView来显示视频。关于SurfaceView的用法,限于篇幅在这里不再赘述。而要将MediaPlayer中解码的视频数据在SurfaceView中播放,需要调用MediaPlayer中的setDisplay()方法,它接受一个SurfaceHolder对象,可以将我们用于播放视频的SurfaceView对应的SurfaceHolder对象作为参数,这样,MediaPlayer和SurfaceView就建立起了关联。还有一个需要注意的是,要正确设置SurfaceView的大小(Size)和视频的大小相匹配。

以下为MediaPlayer中的主要方法和说明:

●setDataSource():设置播放的数据源。参数可以是字符串、FileDescriptor或者Uri等。

●setDisplay():接受一个SurfaceHolder参数,用于设置播放视频的SurfaceView。

●prepare()/prepareAsync():准备MediaPlayer准备播放。它们的区别在于前者是同步方法,后者是异步方法,且后者一般需要配合OnPreparedListener监听器。

●start():开始播放多媒体。

● pause():暂停播放多媒体。

●seekTo():改变播放进度。

●stop():停止播放多媒体。

下面我们来看一个例子:

package com.stylingandroid.viewpager;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

public class MediaPlayerVideo extends Activity implements
OnCompletionListener,
OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {

       private static final String TAG = "MediaPlayerDemo";
       private int mVideoWidth;
       private int mVideoHeight;
       private MediaPlayer mMediaPlayer;
       SurfaceView mPreview;
       private SurfaceHolder holder;
       private String path;
       private Bundle extras;

       private boolean mIsVideoSizeKnown = false;
       private boolean mIsVideoReadyToBePlayed = false;
       /**
       *
       * when the activity is first created.
       */
       @Override
       public void onCreate(Bundle icicle) {
              super.onCreate(icicle);
              setContentView(R.layout.main);
              mPreview = (SurfaceView) findViewById(R.id.surfaceview);
              holder = mPreview.getHolder();
              holder.addCallback(this);
              holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
              extras = getIntent().getExtras();
       }

       private void playVideo() {
              clean();
              try{

                     // 创建一个MediaPlayer对象
                     mMediaPlayer = new MediaPlayer();
                     // 设置播放的视频数据源
                     mMediaPlayer.setDataSource(path);
                     // 将视频输出到SurfaceView
                     mMediaPlayer.setDisplay(holder);
                     // 播放准备,使用异步方式,配合OnPreparedListener
                     mMediaPlayer.prepareAsync();
                     // 设置相关的监听器
                     mMediaPlayer.setOnCompletionListener(this);
                     mMediaPlayer.setOnPreparedListener(this);
                     mMediaPlayer.setOnVideoSizeChangedListener(this);
                     // 设置音频流类型
                     mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }

       public void onCompletion(MediaPlayer arg0) {
              Log.d(TAG, "onCompletion");
       }
       //获得视频的宽和高
       public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
              Log.v(TAG, "onVideoSizeChanged");
              if (width == 0 || height == 0) {
              Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
              return;
       }
       mIsVideoSizeKnown = true;
       mVideoWidth = width;
       mVideoHeight = height;
                if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
                 startVideoPlayback();
                }
        }
        //实现OnPreparedListener中的方法,当视频准备完毕会调用这个回调方法,开始播放
        public void onPrepared(MediaPlayer mediaplayer) {
                 Log.d(TAG, "onPrepared");
                mIsVideoReadyToBePlayed = true;
                if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
                 startVideoPlayback();
                 }
        }

       public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
              Log.d(TAG, "surfaceChanged");
        }

       public void surfaceDestroyed(SurfaceHolder surfaceholder) {
                 Log.d(TAG, "surfaceDestroyed");
         }

       public void surfaceCreated(SurfaceHolder holder) {
                  Log.d(TAG, "surfaceCreated");
                 playVideo();
        }

       @Override
         protected void onPause() {
                 releaseMediaPlayer();
                clean();
                super.onPause();
        }

       @Override
        protected void onDestroy() {
                super.onDestroy();
                releaseMediaPlayer();
                clean();
         }
        // 释放MediaPlayer
        private void releaseMediaPlayer() {
                if (mMediaPlayer != null) {
                 mMediaPlayer.release();
                mMediaPlayer = null;
                }
        }
        // 资源清理工作
        private void clean() {
                mVideoWidth = 0;
                mVideoHeight = 0;
                mIsVideoReadyToBePlayed = false;
                mIsVideoSizeKnown = false;
        }
        // 播放视频的方法
        private void startVideoPlayback() {
                Log.v(TAG, "startVideoPlayback");
                holder.setFixedSize(mVideoWidth, mVideoHeight);
                mMediaPlayer.start();
       }
}

其中的main.xml这个layout很简单,就是一个SurfaceView,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.

android.com/apk/res/android"
       android:orientation="vertical" android:layout_width="fill_parent"
android:gravity="center" android:layout_height="fill_parent">
<SurfaceView android:id="@+id/surfaceView1"
       android:layout_width="800px"
android:layout_height="600px"></SurfaceView>
</LinearLayout>

文章来源:华清远见嵌入式学院原文地址:http://www.embedu.org/Column/Column503.htm

更多相关嵌入式免费资料查看华清远见讲师博文>>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值