Android开发 MediaPlayer入门_播放本地视频
前言
MediaPlayer,可以播放视频/音频,并且它支持本地和网络文件的播放.本片博客作为入门教程,先以最通俗的方式解释播放文件本地视频.(如果你嫌MediaPlayer还是太麻烦可以试试选择VideoView)
实现流程
- 获取权限
- 保持屏幕常亮
- 初始化SurfaceView的状态监听
- 初始化MediaPlayer
- 给MediaPlayer添加预览SurfaceView的SurfaceHolder
- 添加需要播放的视频并且配置MediaPlayer
- 播放视频
- 暂停视频
- 停止视频
- 释放内存
获取权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
播放本地视频,那就需要读写存储权限,注意别忘记了动态授权.另外MediaPlayer是支持网络视频播放的如果你需要播放网络视频则还需要添加网络权限
保持屏幕常亮
音视频开发的基本操作,在xml的根布局上添加下面这个属性,也可以在SurfaceView上添加
android:keepScreenOn="true"
初始化SurfaceView
作为显示播放视频的曲面View,如果你还不了解它.那么建议你先学习一些SurfaceView的知识.
我们需要监听SurfaceView状态,确定它启动完毕之后我们在开始加载播放视频.在onCreate执行下面的初始化initSurfaceviewStateListener
private void initSurfaceviewStateListener() {
mSurfaceHolder = mVideoPlaySurfaceview.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);//给mMediaPlayer添加预览的SurfaceHolder
setPlayVideo(mPath);//添加播放视频的路径
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG, "surfaceChanged触发: width=" + width + "height" + height); } @Override
public void surfaceDestroyed(SurfaceHolder holder) { }
});
}
在surfaceCreated方法里执行了2个方法:(当然可以先不关注,下面依然会重新提到它们)
- 给MediaPlayer添加预览的SurfaceHolder.
- 添加播放视频的路径与配置MediaPlayer
初始化MediaPlayer
private void initMediaPalyer() {
mMediaPlayer = new MediaPlayer(); }
直接new,没说明好说的,也是可以先在onCreate执行initMediaPalyer
给MediaPlayer添加预览SurfaceView的SurfaceHolder
SurfaceView初始化完成后直接给MediaPlayer设置SurfaceHolder >>>>> mMediaPlayer.setDisplay(holder);
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);//给mMediaPlayer添加预览的SurfaceHolder
setPlayVideo(mPath);//添加播放视频的路径
}
添加需要播放的视频并且配置MediaPlayer
private void setPlayVideo(String path) {
try {
mMediaPlayer.setDataSource(path);//设置播放视频文件
mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);//缩放模式
mMediaPlayer.setLooping(true);//设置循环播放
mMediaPlayer.prepareAsync();//异步准备
// mMediaPlayer.prepare();//同步准备,因为是同步在一些性能较差的设备上会导致UI卡顿
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { //准备完成回调
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();//启动播放视频
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
setPlayVideo方法,在surfaceCreated接口回调方法里执行即可.上面已经有写就不在重复交代了
播放视频
private void startPlay(){
if (!mMediaPlayer.isPlaying()){ //判断视频是否在播放
mMediaPlayer.start();
}
}
暂停视频
private void pausePlay(){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}
}
停止视频
private void stopPlay(){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
}
释放内存
这是必要的,因为MediaPlayer底层是运行C++的函数方法.不要使用后,必需释放内存
@Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
mMediaPlayer.release();
mMediaPlayer = null;
}
}
API总汇
- 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):当装载流媒体完毕的时候回调。
- setOnInfoListener(OnInfoListener l) 信息监听
mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
//what 对应返回的值如下
// public static final int MEDIA_INFO_UNKNOWN = 1; 媒体信息未知
// public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; 媒体信息视频跟踪滞后
// public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; 媒体信息\视频渲染\开始
// public static final int MEDIA_INFO_BUFFERING_START = 701; 媒体信息缓冲启动
// public static final int MEDIA_INFO_BUFFERING_END = 702; 媒体信息缓冲结束
// public static final int MEDIA_INFO_NETWORK_BANDWIDTH = 703; 媒体信息网络带宽(703)
// public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; 媒体-信息-坏-交错
// public static final int MEDIA_INFO_NOT_SEEKABLE = 801; 媒体信息找不到
// public static final int MEDIA_INFO_METADATA_UPDATE = 802; 媒体信息元数据更新
// public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; 媒体信息不支持字幕
// public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; 媒体信息字幕超时 return false;
}
});
贴心周到,贴全demo代码,给你查缺补漏
xml文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:keepScreenOn="true"
android:background="@color/colorBlack1"
tools:context=".work.share.VideoPlayActivity"> <SurfaceView
android:id="@+id/video_play_surfaceview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/> <ImageView
android:id="@+id/start_and_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_start"
android:layout_marginBottom="50dp"
android:layout_marginLeft="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
activity
import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.pm.ActivityInfo;
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.widget.ImageView;
import com.yt.kangaroo.R;
import com.yt.kangaroo.app.BaseActivity;
import java.io.File;
import java.io.IOException;
/**
*@content:视频播放activity
*@time:2019-6-13
*@build:
*/ public class VideoPlayActivity extends BaseActivity implements View.OnClickListener {
private static final String TAG = VideoPlayActivity.class.getSimpleName();
private SurfaceView mVideoPlaySurfaceview;
private ImageView mStartAndStop;
private MediaPlayer mMediaPlayer;
private String mPath;
private boolean isInitFinish = false;
private SurfaceHolder mSurfaceHolder; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
File file = new File(getExternalCacheDir(), "demo.mp4");
mPath = file.getAbsolutePath();
initMediaPalyer();
initSurfaceviewStateListener(); } @Override
protected void onPause() {
super.onPause();
pausePlay();
} @Override
public int getLayout() {
return R.layout.activity_video_play;
} @Override
public void initView() {
mVideoPlaySurfaceview = findViewById(R.id.video_play_surfaceview);
mStartAndStop = findViewById(R.id.start_and_stop);
mStartAndStop.setOnClickListener(this); } @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_and_stop:
if (mMediaPlayer.isPlaying()) {
pausePlay();
mStartAndStop.setImageResource(R.mipmap.ic_start);
} else {
startPlay();
mStartAndStop.setImageResource(R.mipmap.ic_stop);
}
break;
default:
break;
} } private void initSurfaceviewStateListener() {
mSurfaceHolder = mVideoPlaySurfaceview.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);//给mMediaPlayer添加预览的SurfaceHolder
setPlayVideo(mPath);//添加播放视频的路径
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG, "surfaceChanged触发: width=" + width + "height" + height); } @Override
public void surfaceDestroyed(SurfaceHolder holder) { }
});
} private void initMediaPalyer() {
mMediaPlayer = new MediaPlayer(); } private void setPlayVideo(String path) {
try {
mMediaPlayer.setDataSource(path);//
mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);//缩放模式
mMediaPlayer.setLooping(true);//设置循环播放
mMediaPlayer.prepareAsync();//异步准备
// mMediaPlayer.prepare();//同步准备,因为是同步在一些性能较差的设备上会导致UI卡顿
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { //准备完成回调
@Override
public void onPrepared(MediaPlayer mp) {
isInitFinish = true;
mp.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
} private void startPlay(){
if (!mMediaPlayer.isPlaying()){
mMediaPlayer.start();
}
} private void stopPlay(){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
} private void pausePlay(){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}
} private void seekTo(int time){
mMediaPlayer.seekTo(time);
} @Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
mMediaPlayer.release();
mMediaPlayer = null;
}
} }
end
Android开发 MediaPlayer入门_播放本地视频的更多相关文章
- Android中webview html5 自动播放本地视频
MainActivity代码 public class Html5VideoAutoPlay extends Activity { WebView webview = null; @Override ...
- 照相、从相册上取照片、播放音频、播放本地视频、播放网络视频、MPMoviePlayerController
一.照相.从相册上去照片 1. 先判断是否支持照相功能 *判断当前设备是否支持照相功能,支持返回YES 否则返回NO 注意:模拟器不支持照相功能 把握一个原则只要是物理硬件相关的功能模拟器都不支持 例 ...
- Swift - 使用Media Player播放本地视频,在线视频
Media Player框架用于播放本地视频.音频,也可以在线播放视频和音频. 1,播放器MPMovieControlStyle样式有如下几种: (1)None: 没有播放控制控件 (2)Embedd ...
- 学Android开发,入门语言java知识点
学Android开发,入门语言java知识点 Android是一种以Linux为基础的开源码操作系统,主要使用于便携设备,而linux是用c语言和少量汇编语言写成的,如果你想研究Android,就去学 ...
- 「Android 开发」入门笔记
「Android 开发」入门笔记(界面编程篇) ------每日摘要------ DAY-1: 学习笔记: Android应用结构分析 界面编程与视图(View)组件 布局管理器 问题整理: Andr ...
- 使用Ant搭建Android开发环境入门
使用Ant搭建Android开发环境入门 使用Ant搭建Android开发环境,建立android项目 配置Ant环境 下载Ant:http://ant.apache.org/bindownloa ...
- potplayer 网页调用potplayer播放本地视频
网页调用potplayer播放本地视频 CreateTime--2018年1月3日10:36:24 Author:Marydon 源码展示: <!DOCTYPE html> <h ...
- Android 视频播放器 VideoView 的使用,播放本地视频 和 网络 视频
1.布局文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...
- Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例
前言:前面一篇我们介绍MediaPlayer相关方法,有人说,没有实际例子,看得不是很明白,今天在分析MediaPlayer时,顺带一个播放网络视频例子.可以自行试试.今天分析的都是下几篇介绍各个模块 ...
随机推荐
- python之将Unicode文本标准化
在需要比较字符串的程序中使用字符的多种表示会产生问题. 为了修正这个问题,你可以使用unicodedata模块先将文本标准化: s1 = 'Spicy Jalape\u00f1o' s2 = 'Spi ...
- MySQL - Lock wait timeout exceeded
今天突然出了个奇怪的问题,原本正常启动的项目,在什么都没有修改的情况下,启动到一半的时候会卡住几分钟,几分钟后又成功启动了,刚好是卡在Quartz那里,还以为出什么奇奇怪怪的幺蛾子了,一看日志,数据库 ...
- LeetCode Array Easy 167. Two Sum II - Input array is sorted
Description Given an array of integers that is already sorted in ascending order, find two numbers s ...
- JAVA基础学习-多态 对象转型 final
一.多态的产生条件 1:继承 存在继承的类之间 2:方法重装 3:父类继承子类重装的方法 子类的对象 也是属于父类的 二:对象的转型 1:向上转型:当子类转型成父类时 例如:Animal a = n ...
- 数据库常用SQL语句
显示所有的数据库 show databases; 新建数据库 create database if not exists 数据库名 default character set = 'utf8'; 删 ...
- Centos7.2安装MariaDB数据库,并进行基础配置
[注] MariaDB的安装与配置感谢博主carlo-jie的分享,原博文地址https://www.cnblogs.com/carlo-jie/p/6104135.html. 第二小节:用户创建及权 ...
- vue笔记一:设置表头的背景颜色以及下边框颜色
最近做的一个项目有个小小的需求,就是把表头的背景颜色改为黑色,表格边框颜色改为这个颜色,中间出了些问题,因为vue的表格样式是内联样式,一修改就影响到其他地方的表格样式,尽管我单独加了id还是不行,经 ...
- npm install 超时 国内 切换源; npm ERR! code ELIFECYCLE;
install 超时 查看npm源地址 npm config get registry #http://registry.npmjs.org 为国外镜像地址 设置阿里云镜像 npm config se ...
- 本地JAR包打入本地mvn仓库
新建目录my-lib,将jar包移动到目录中,添加pom文件(用alipay测试) <project xmlns="http://maven.apache.org/POM/4.0.0& ...
- Mysql数据库命令行输入错误怎么办
Mysql数据库命令行输入错误 缺少另一半 错误输入 ' 或 " 时,必须键入另一半才能退出命令. 缺少分号 写入语句缺少分号需要补全. 输入quit或者exit退出 ctrl+c,完全退出 ...