安卓使用MediaPlayer自定义音频视频播放器
全栈工程师开发手册 (作者:栾鹏)
安卓教程全解
安卓使用MediaPlayer,一般还要配置一个播放画面SurfaceView,和一个进度条SeekBar。
视频的播放会更改进度条的进度,也可以手动更改进度条来调节视频时间。MediaPlayer不想videoview以及集成了SurfaceView和MediaPlayer的相关准备,所以需要手动实现的功能还有很多。这里先实现一个播放器类。完成视频控制的功能。
下面的代码存储为Player.java类,内容中先
package com.lp.app.media;import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.SeekBar;//自定义视频播放器,使用MediaPlayer播放视频,需要制作视频界面,渲染数据的surfaceView(屏幕缓冲区)、滚动条SeekBar和播放前准备,public class Player implements OnBufferingUpdateListener,OnCompletionListener, MediaPlayer.OnPreparedListener,SurfaceHolder.Callback{private int videoWidth;private int videoHeight;public MediaPlayer mediaPlayer; //媒体播放器private SurfaceHolder surfaceHolder; //渲染画面private SeekBar skbProgress; //播放进度private Timer mTimer=new Timer();public Player(SurfaceView surfaceView,SeekBar skbProgress){this.skbProgress=skbProgress;this.skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());surfaceHolder=surfaceView.getHolder();surfaceHolder.addCallback(this);surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);mTimer.schedule(mTimerTask, 0, 1000);}//通过定时器和Handler来更新进度条TimerTask mTimerTask = new TimerTask() {@Overridepublic void run() {if(mediaPlayer==null)return;if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {handleProgress.sendEmptyMessage(0);}}};//主界面接收消息更新进度条uiHandler handleProgress = new Handler() {public void handleMessage(Message msg) {int position = mediaPlayer.getCurrentPosition();int duration = mediaPlayer.getDuration();if (duration > 0) {long pos = skbProgress.getMax() * position / duration;skbProgress.setProgress((int) pos);}};};//启动播放public void play(){mediaPlayer.start();}//播放在线视频public void playUrl(String videoUrl){try {mediaPlayer.reset();mediaPlayer.setDataSource(videoUrl);mediaPlayer.prepare();//prepare之后自动播放//mediaPlayer.start();Log.v("mediaPlayer", "在线视频开始播放");} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//暂停public void pause(){mediaPlayer.pause();}//停止播放public void stop(){if (mediaPlayer != null) { mediaPlayer.stop();mediaPlayer.release(); mediaPlayer = null; } }//跳转到多少毫秒public void seekTo(int ms){mediaPlayer.seekTo(ms); //加载到多少毫秒}//SurfaceView创建时调用
@Override
public void surfaceCreated(SurfaceHolder holder) {try {mediaPlayer = new MediaPlayer();mediaPlayer.setDisplay(surfaceHolder);mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setOnBufferingUpdateListener(this);mediaPlayer.setOnPreparedListener(this); //视频准备就绪事件Log.v("mediaPlayer", "视频准备就绪");} catch (Exception e) {Log.e("mediaPlayer", "error", e);}}@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {Log.v("mediaPlayer", "surface变化");
}@Override
public void surfaceDestroyed(SurfaceHolder holder) {Log.v("mediaPlayer", "surface销毁");
}//视频准备就绪事件,启动播放
@Override
public void onPrepared(MediaPlayer mp) {videoWidth = mediaPlayer.getVideoWidth();videoHeight = mediaPlayer.getVideoHeight();if (videoHeight != 0 && videoWidth != 0) {mp.start();}Log.v("mediaPlayer", "视频启动");
}@Override
public void onCompletion(MediaPlayer mp) {Log.v("mediaPlayer", "视频完成");
}//缓冲进度变化事件(不是播放进度),其中percent是0~100的整数,代表已经缓冲好的多媒体数据的百分比
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {skbProgress.setSecondaryProgress(percent);int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();Log.v("播放进度"+currentProgress+"% play", "缓冲进度"+percent + "% buffer");
}//进度条监控,进度条变化要更改进度显示和视频时间。
class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {int progress;@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()this.progress = progress * mediaPlayer.getDuration()/seekBar.getMax();}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字seekTo(progress);}}}
然后我要自定义实现一个视频播放画面。mediaplay.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"><LinearLayoutandroid:layout_alignParentTop="true"android:id="@+id/mediaplay_linear"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><Buttonandroid:id="@+id/mediaplay_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="启动" /><Buttonandroid:id="@+id/mediaplay_pause"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="暂停" /><Buttonandroid:id="@+id/mediaplay_stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="停止" /></LinearLayout><SurfaceViewandroid:layout_below="@id/mediaplay_linear"android:id="@+id/mediaplay_surfaceView"android:layout_width="match_parent"android:layout_height="wrap_content" /><SeekBarandroid:layout_below="@id/mediaplay_linear"android:id="@+id/mediaplay_seekbar"android:layout_width="match_parent"android:layout_height="wrap_content" /></RelativeLayout>
最后再activity中实现播放器类的调用和播放基本控制。
其中用户点击进度条调整观看的时间点,可以写在播放类player中,也可以写在activity中,而且最好写在activity中,因为除了点击进度条除了调整视频时间,可能还会调整其他UI。
package com.lp.app.media;import com.lp.app.R;
import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;//使用MediaPlayer播放视频,需要将视频界面,渲染surface和播放前准备,//影片的时间变化,进度条变化,时间的提示变化要同步。用户可以通过进度条控制视频时间跳转.
public class MediaplayActivity extends Activity {Context context;SurfaceView surfaceView;public MediaPlayer mediaPlayer; //媒体播放器private SeekBar skbProgress;private Player player;private Button btnPause, btnStart, btnStop;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.mediaplay);context=this;surfaceView = (SurfaceView)findViewById(R.id.mediaplay_surfaceView);btnStart = (Button)findViewById(R.id.mediaplay_start);btnPause = (Button)findViewById(R.id.mediaplay_pause);btnStop = (Button)findViewById(R.id.mediaplay_stop);btnStart.setOnClickListener(new ClickEvent());btnPause.setOnClickListener(new ClickEvent());btnStop.setOnClickListener(new ClickEvent());skbProgress = (SeekBar) this.findViewById(R.id.mediaplay_seekbar);player = new Player(surfaceView, skbProgress);}//点击事件class ClickEvent implements OnClickListener {@Overridepublic void onClick(View view) {if (view == btnPause) {player.pause();} else if (view == btnStart) {String url="http://www.525heart.com/test.mp4";player.playUrl(url);} else if (view == btnStop) {player.stop();}}}
安卓使用MediaPlayer自定义音频视频播放器相关推荐
- 移动应用程序设计基础——安卓动画与视音频播放器的实现
<移动应用程序设计基础>实验6 安卓动画与视音频播放器的实现 实验名称: 实验6 安卓动画与视音频播放器的实现 所使用的工具软件及环境: JDK1.8,Android Studio 一.实 ...
- MediaPlayer+SurfaceView实现视频播放器
我这个人走得很慢,但是我从不后退. 之前给大家分享过使用MediaController类实现视频播放器,今天呢给大家分享可以自定义的视频播放器,那就是使用MediaPlayer+SurfaceView ...
- vue自定义音频播放组件_易于创建Vue的自定义音频播放器组件
vue自定义音频播放组件 音频更好 (vue-audio-better) Easy to create custom audio player components for Vue.js. 易于为Vu ...
- android播放器竖屏,SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,
MNVideoPlayer SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,手势快进快退.调节音量,亮度等.之前也发布过一个视频播放列表, 项目截图: 使用步骤: ...
- 自定义音频播放器_创建自定义HTML5音频播放器
自定义音频播放器 在本教程中,我将向您介绍HTML5音频,并向您展示如何创建自己的播放器. 如果您想走捷径,请查看Envato市场上可用的现成的HTML5音频播放器 . 它使您可以从各种来源创建播放列 ...
- android音频视频播放器
最近写了一个android简单的音频视频播放器,顺便开源了 1.扫描sdcard的音乐文件并播放 2.歌词同步功能(只能同步到行,因为是lrc格式,如果需要同步到每一个字,类似kogou那样则需要解析 ...
- Video标签自定义简易视频播放器
Video标签自定义简易视频播放器 提示:以下是本篇文章正文内容,下面案例可供参考 一.Dom结构 <template><el-dialog :title="winTitl ...
- 自定义Android视频播放器 - 切换横竖屏
前一篇自定义了SurfaceView,然后尝试横屏显示,虽然视频适配方面没有问题,但是没有占满整个屏幕. 我分析了一下一般的视频播放器,发现: 竖屏播放视频,播放器的宽度占满手机屏幕的宽度,播放器的高 ...
- MediaPlayer+TextureView实现视频播放器
Android中实现视频播放器的途径有两种: 使用VideoView 通过MediaPlayer + SurfaceView/ TextureView 1. VideoView VideoView使用 ...
最新文章
- 售前比售后机器人控制逻辑更复杂,仅凭大规模数据后发优势难赶超!
- POJ 2480 (约数+欧拉函数)
- android accessibility 模拟键盘事件_H5 键盘兼容性小结
- [BZOJ 1588] [HNOI 2002] 营业额统计
- 保留小数点后两位小数
- python获取命令行参数_【整理】Python中如何获得并处理命令行参数
- delphi制作上下开幕效果_显示产业国际盛会开幕,广州新型显示产值将突破2500亿...
- Java时间格式转换输出实现代码示例
- 一个基于.NET Core3.1的开源项目帮你彻底搞懂WPF框架Prism
- es7 如何从项目resource读取index的mapping、setting.json文件
- SpringCloud2.0 集成分布式事务管理 LCN
- [转载]Android学习网站
- 为什么中国程序员工资那么高,连一个 MATLAB 的替代品都开发不出来?
- Scikit-learn_聚类算法_K均值聚类
- ESXi Arm Edition version 1.11更新,及安装Win11 Arm版
- 下载网页上的视频—Flash Video Downloader插件
- 湖北物联网产业标准联盟成立
- eclipse安装devstyle插件失败问题AN error occurred while colleting items tobe installed
- Coding and Paper Letter(六十)
- 福利来了!教你们怎么把整个网站的漂亮小姐姐视频都给爬下来!
热门文章
- 人物 | 当我们在谈论语音识别时,我们在谈些什么?——知乎达人、CMU博士生王赟...
- php10天速成培训,十天学会php之第九天
- 面试题 02.01. 移除重复节点(链表删除操作模板)
- H.264参考软件JM12.2RC代码详细流程
- java 综合练习_Java 之综合练习
- 2021牛客暑期多校训练营8,签到题ADEK
- 如何进行文件管理、备份
- 【编译器】G++相关编译命令
- msf 生成php马_PHP的性能优化方法总结
- Python入门--第三方模块的安装与使用,pip,import