zoukankan      html  css  js  c++  java
  • Android 视频播放器 (二):使用MediaPlayer播放视频

    在 Android 视频播放器 (一):使用VideoView播放视频 我们讲了一下如何使用VideoView播放视频,了解了基本的播放器的一些知识和内容。也知道VideoView内部封装的就是MediaPlayer,本文就介绍如何使用MediaPlayer播放视频。

    一、简介

    MediaPlayer是Android中的一个多媒体播放类,其提供的API能满足简单的大部分音视频的播放需求。

    下面简单介绍一下MediaPlayer:

    • MediaPlayer是使用Surface进行视频的展示的。
    • MediaPlayer只支持mp4、avi、3gp格式的视频,支持格式相对单一。
    • MediaPlayer可以播放网络视频,支持的网络视频的协议为:Http协议和RTSP协议两种。

    二、MediaPlayer 使用方法

    MediaPlayer 的提供的方法如下:

    • void setDataSource(String path) :通过一个具体的路径来设置MediaPlayer的数据源,path可以是本地的一个路径,也可以是一个网络路径
    • void setDataSource(Context context, Uri uri): 通过给定的Uri来设置MediaPlayer的数据源,这里的Uri可以是网络路径或是一个ContentProvider的Uri。
    • void setDataSource(MediaDataSource dataSource) :通过提供的MediaDataSource来设置数据源
    • void setDataSource(FileDescriptor fd): 通过文件描述符FileDescriptor来设置数据源
    • int getCurrentPosition() :获取当前播放的位置
    • int getAudioSessionId() :返回音频的session ID
    • int getDuration() :得到文件的时间
    • TrackInfo[] getTrackInfo() :返回一个track信息的数组
    • boolean isLooping (): 是否循环播放
    • boolean isPlaying(): 是否正在播放
    • void pause () :暂停
    • void start () :开始
    • void stop () : 停止
    • void prepare(): 同步的方式装载流媒体文件。
    • void prepareAsync(): 异步的方式装载流媒体文件。
    • void reset(): 重置MediaPlayer至未初始化状态。
    • void release (): 回收流媒体资源。
    • void seekTo(int msec): 指定播放的位置(以毫秒为单位的时间)
    • void setAudioStreamType(int streamtype) :指定流媒体类型
    • void setLooping(boolean looping) :设置是否单曲循环
    • void setNextMediaPlayer(MediaPlayer next) : 当前这个MediaPlayer播放完毕后,MediaPlayer next开始播放
    • void setWakeMode(Context context, int mode):设置CPU唤醒的状态。
    • setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) :网络流媒体的缓冲变化时回调 
    • setOnCompletionListener(MediaPlayer.OnCompletionListener listener) :网络流媒体播放结束时回调
    • setOnErrorListener(MediaPlayer.OnErrorListener listener) :发生错误时回调 
    • setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当装载流媒体完毕的时候回调。

    Android通过MediaPlayer控制播放器的状态的方式来控制媒体文件的播放,其中: 

    • prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
    • start()是真正启动文件播放的方法, 
    • pause()和stop()比较简单,起到暂停和停止播放的作用, 
    • seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。 
    • release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。 
    • reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。

    使用MediaPlayer播放视频的步骤如下:

    1. 创建MediaPlayer对象,并让它加载指定的视频文件;
    2. 在界面布局文件中定义SurfaceView控件,或在程序中创建SurfaceView控件,并为SurfaceView的SurfaceHolder添加Callback监听器;
    3. 调用MediaPlayer对象的setDisney(SurfaceHolder sh)方法将所播放的视频图像输出到指定的SurfaceView控制;
    4. 调用MediaPlayer的start()、stop()、pause()方法来控制视频播放。
    下图是一个MediaPlayer对象被支持的播放控制操作驱动的声明周期和状态。其中,椭圆代表MediaPlayer可能驻留的状态,弧线表示驱动MediaPlayer在各个状态之间迁移的播放控制操作。这里有两种类型的弧线。由单箭头开始的弧线代表同步方法调用,而以双箭头开头的弧线代表异步方法调用。

    三、使用MediaPlayer实现视频播放

    下面我们将展示如何使用MediaPlayer播放香港卫视的视频流:

    1. 声明权限

    需要在AndroidManifest.xml添加权限。

    <uses-permission android:name="android.permission.INTERNET" />

    2. 编写SurfaceView布局

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <SurfaceView
                android:id="@+id/surface_view"
                android:layout_width="match_parent"
                android:layout_height="195dp" />
        </LinearLayout>
    </android.support.constraint.ConstraintLayout>

    3. 编写播放视频代码

    public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    
        SurfaceView surfaceView;
    
        SurfaceHolder surfaceHolder;
    
        MediaPlayer mediaPlayer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            surfaceView = findViewById(R.id.surface_view);
    
            surfaceHolder = surfaceView.getHolder();
    
            surfaceHolder.addCallback(this);
    
            mediaPlayer = new MediaPlayer();
    
            try {
                mediaPlayer.setDataSource("http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Surface surface = holder.getSurface();
            mediaPlayer.setSurface(surface);
            mediaPlayer.prepareAsync();
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
    
        }
    }

    四、MediaPlayer使用注意事项

    1. 在使用start()播放流媒体之前,需要装载流媒体资源。这里最好使用prepareAsync()用异步的方式装载流媒体资源。因为流媒体资源的装载是会消耗系统资源的,在一些硬件不理想的设备上,如果使用prepare()同步的方式装载资源,可能会造成UI界面的卡顿,这是非常影响用于体验的。因为推荐使用异步装载的方式,为了避免还没有装载完成就调用start()而报错的问题,需要绑定MediaPlayer.setOnPreparedListener()事件,它将在异步装载完成之后回调。异步装载还有一个好处就是避免装载超时引发ANR((Application Not Responding)错误。
      mediaPlayer = new MediaPlayer();
      mediaPlayer.setDataSource(path);
      mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
      // 通过异步的方式装载媒体资源
      mediaPlayer.prepareAsync();
      mediaPlayer.setOnPreparedListener(new OnPreparedListener() {                    
           @Override
           public void onPrepared(MediaPlayer mp) {
                // 装载完毕回调
                mediaPlayer.start();
           }
      });
    1. 使用完MediaPlayer需要回收资源。MediaPlayer是很消耗系统资源的,所以在使用完MediaPlayer,不要等待系统自动回收,最好是主动回收资源
      if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
      }
  • 相关阅读:
    前端chrome浏览器调试总结
    this指南——绑定了谁?
    轮播图终极版
    一个后台项目的总结
    h5 websocket 断开重新连接
    ios手机键盘拉起之后页面不会回退的问题
    promise 的串行执行
    js中对小数的计算
    对问卷项目的优化
    禁止eslint对指定代码检测
  • 原文地址:https://www.cnblogs.com/renhui/p/9269040.html
Copyright © 2011-2022 走看看