IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android MediaPlayer基础 -> 正文阅读

[移动开发]Android MediaPlayer基础


前言

Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频 该类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最少的步骤来获取,解码 和播放音视频。它支持三种不同的媒体来源:

  • 本地资源
  • 内部的URI,比如你可以通过ContentResolver来获取
  • 外部URL(流) 对于Android所支持的的媒体格式列表

一、MedaiPlayer状态图

音频/视频文件和流的播放控制作为状态机进行管理。下图显示了受支持的播放控制操作驱动的 MediaPlayer 对象的生命周期和状态。椭圆表示 MediaPlayer 对象可能驻留的状态。弧表示驱动对象状态转换的播放控制操作。有两种类型的弧。带单箭头的弧表示同步方法调用,带双箭头的弧表示异步方法调用。
MediaPlayer状态图
从这个状态图中,可以出MediaPlayer对象具有以下状态:

  1. MediaPlayer在使用new或者reset()之后,它处于idle状态,并且在release()被调用之后,它处于结束状态。

       当处于除End状态外,都可以调用reset()把Mediaplayer置为idle状态。
       当MediaPlayer对象不再使用后,需要调用relase()释放资源,使它转为End状态。
    
  2. 通过注册的setOnErrorListener(android.media.MediaPlayer.OnErrorListener)事件可以获取到一些编程错误信息。

  3. idle状态状态下调用setDataSource(),将idle状态的MediaPlayer对象转到initialized状态。(在其他状态调用setDataSource会抛出IllegalStateException错误。)

  4. MediaPlayer需要进入Prepared状态后,才能开始播放。

    可以通过两种方式到达Prepared状态:
    1、同步,调用prepare(),调用返回后将对象转移到Prepared状态。
    2、异步,调用prepareAsync(),首先在调用返回后(几乎立即发生)进入Preparing状态,而内部播放器引擎继续处理其余的准备工作,直到准备工作完成。之后会触发setOnPreparedListener回调。
    
  5. 要开始播放,start()必须调用,调用start()成功后进入started状态。

  6. 调用pause(),进入Paused状态。

  7. 调用stop(),进入Stopped状态,stop状态后需要进入Prepared状态才能开始播放。

  8. 当播放到达流的末尾时,播放完成。

     需要setLooping为false,才会进入PlaybackCompleted。
     setLooping为true,,MediaPlayer 对象会会保持在Started状态
    
  9. 在PlaybackCompleted 状态下,调用start()可以从音频/视频源的开头重新开始播放。

二、案例

package com.cs.testmediaplayer;

import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;

import androidx.appcompat.app.AppCompatActivity;


public class MainActivity extends AppCompatActivity {
    SurfaceView mSvVideoPlayer;

    private MediaPlayer mMediaPlayer;
    private int mPosition = 0;
    private boolean hasActiveHolder = false;
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSvVideoPlayer = findViewById(R.id.sv_video_player);
        playVideo();
    }

    /**
     * 播放视频
     */
    public void playVideo() {
        if (mMediaPlayer == null) {
            //实例化MediaPlayer对象
            mMediaPlayer = new MediaPlayer();
            mSvVideoPlayer.setVisibility(View.VISIBLE);
            // mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            boolean mHardwareDecoder = false;
            // 不维持自身缓冲区,直接显示
            //  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && mHardwareDecoder) {
            mSvVideoPlayer.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            // }
            mSvVideoPlayer.getHolder().setFixedSize(getScreenWidth(), getScreenHeight());
            mSvVideoPlayer.getHolder().setKeepScreenOn(true);//保持屏幕常亮
            mSvVideoPlayer.getHolder().addCallback(new SurFaceCallback());

        }
    }

    /**
     * 向player中设置dispay,也就是SurfaceHolder。但此时有可能SurfaceView还没有创建成功,所以需要监听SurfaceView的创建事件
     */
    private final class SurFaceCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (mMediaPlayer == null) {
                return;
            }
            if (!hasActiveHolder) {
                play(mPosition);
                hasActiveHolder = true;
            }
            if (mPosition > 0) {
                play(mPosition);
                mPosition = 0;
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mMediaPlayer == null) {
                return;
            }
            mMediaPlayer.setScreenOnWhilePlaying(true);
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.stop();
                mPosition = mMediaPlayer.getCurrentPosition();
            }
        }

        private void play(int position) {
            try {
                //添加播放视频的路径与配置MediaPlayer
                //  AssetFileDescriptor fileDescriptor = getResources().openRawResourceFd(R.raw.info);
                mMediaPlayer.reset();
                //给mMediaPlayer添加预览的SurfaceHolder,将播放器和SurfaceView关联起来
                mMediaPlayer.setDisplay(mSvVideoPlayer.getHolder());
                //  mMediaPlayer.setDataSource(path );
                //mMediaPlayer.setDataSource("https://vjs.zencdn.net/v/oceans.mp4");
                //mMediaPlayer.setDataSource("http://172.29.163.154:8080/resoure/boon.mp4");
                //https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv
                // mMediaPlayer.setDataSource("https://html5demos.com/assets/dizzy.mp4");
                mMediaPlayer.setDataSource("https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv");
                Log.d(TAG, "setDataSource: ");

                mMediaPlayer.stop();
                // 缓冲
                mMediaPlayer.prepareAsync();

                mMediaPlayer.setOnBufferingUpdateListener(new BufferingUpdateListener());

                mMediaPlayer.setOnPreparedListener(new PreparedListener(position));

                mMediaPlayer.setOnCompletionListener(new CompletionListener());

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 缓冲变化时回调
     */
    private final class BufferingUpdateListener implements MediaPlayer.OnBufferingUpdateListener {

        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            if (mMediaPlayer != null) {
                if (mMediaPlayer.isPlaying()) {
                    mMediaPlayer.pause();
                    mPosition = mMediaPlayer.getCurrentPosition();
                } else {
                    mMediaPlayer.start();
                    mMediaPlayer.seekTo(mPosition);
                }
            }
            mMediaPlayer.stop();

        }
    }

    /**
     * 准备完成回调
     * 只有当播放器准备好了之后才能够播放,所以播放的出发只能在触发了prepare之后
     */
    private final class PreparedListener implements MediaPlayer.OnPreparedListener {
        private int position;

        public PreparedListener(int position) {
            Log.d(TAG, "PreparedListener ");
            this.position = position;
            mMediaPlayer.start();
        }

        @Override
        public void onPrepared(MediaPlayer mp) {
            Log.d(TAG, "onPrepared:start ");
            mMediaPlayer.start();
            if (position > 0) {
                mMediaPlayer.seekTo(position);
            }
        }
    }

    /**
     * 播放结束时回调
     */
    private final class CompletionListener implements MediaPlayer.OnCompletionListener {

        @Override
        public void onCompletion(MediaPlayer mp) {
            ///   mMediaPlayer.start();
        }
    }

    @Override
    public void onDestroy() {
        //释放内存,MediaPlayer底层是运行C++的函数方法,不使用后必需释放内存
        if (mMediaPlayer != null) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                mPosition = mMediaPlayer.getCurrentPosition();
            }
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        super.onDestroy();
    }

    private int getScreenWidth() {
        return ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
    }

    private int getScreenHeight() {
        return ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
                .getHeight();
    }
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-07 21:17:37  更:2021-07-07 21:17:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 15:28:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码