Android播放器的三种实现方法
转载自:http://blog.csdn.net/wozuihaole/article/details/60867076
今天来说一下Android中怎么实现视频播放,我主要说三种:
1.MediaPlayer+SurfaceView;
2.VideoView;
3.Vitamio框架。
1.MediaPlayer+SurfaceView这种方法是基础,后面的两种方法其实就是把这种方法封装了一下,使用起来更方便些。
我认为大家基本都会用MediaPlayer这个API,我们都知道MediaPlayer是媒体播放器,可以播放音频,视频其实就是给音频配上影像,而SurfaceView就是给音频配上影像的工具,我们只需要把SurfaceView与MediaPlayer关联起来就行了。
主要代码:
SurfaceHolder holder = SurfaceView.getHolder();
MediaPlayer.setDisplay(holder);//将影像播放控件与媒体播放控件关联起来
我认为之前不知道的代码可能只有这两句。
布局代码:
效果图
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.video.MainActivity" android:layout_margin="10dp" android:orientation="vertical"> <EditText android:id="@+id/et" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入文件名称例如:aa.mp4,务必确保文件放在sdcard目录下"/> <SurfaceView android:id="@+id/sfv" android:layout_width="match_parent" android:layout_marginTop="10dp" android:layout_height="200dp" /> <SeekBar android:id="@+id/sb" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <Button android:id="@+id/play" android:layout_width="0dp" android:layout_height="60dp" android:layout_weight="1" android:onClick="play" android:text="播放"/> <Button android:id="@+id/pause" android:layout_width="0dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_weight="1" android:onClick="pause" android:text="暂停"/> <Button android:layout_width="0dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_weight="1" android:onClick="stop" android:text="停止"/> <Button android:layout_width="0dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_weight="1" android:onClick="replay" android:text="重播"/> </LinearLayout> </LinearLayout>
完整代码+注释:
package com.example.video; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.SeekBar; import android.widget.Toast; import java.io.File; import java.io.IOException; import java.util.Timer; import java.util.TimerTask; /** * 需要注意的是我实验了.mp4,3gp和avi3种格式的视频,在5.1的真机和模拟器上avi格式都是只有声音没有影像,其他两种格式 * 播放正常。 */ public class MainActivity extends Activity {private SurfaceView sfv;//能够播放图像的控件 private SeekBar sb;//进度条 private String path ;//本地文件路径 private SurfaceHolder holder; private MediaPlayer player;//媒体播放器 private Button Play;//播放按钮 private Timer timer;//定时器 private TimerTask task;//定时器任务 private int position = 0; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); }//初始化控件,并且为进度条和图像控件添加监听 private void initView() {sfv = (SurfaceView) findViewById(R.id.sfv); sb = (SeekBar) findViewById(R.id.sb); Play = (Button) findViewById(R.id.play); et = (EditText) findViewById(R.id.et); Play.setEnabled(false); holder = sfv.getHolder(); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}@Override public void onStartTrackingTouch(SeekBar seekBar) {}@Override public void onStopTrackingTouch(SeekBar seekBar) {//当进度条停止拖动的时候,把媒体播放器的进度跳转到进度条对应的进度 if (player != null) {player.seekTo(seekBar.getProgress()); }}}); holder.addCallback(new SurfaceHolder.Callback() {@Override public void surfaceCreated(SurfaceHolder holder) {//为了避免图像控件还没有创建成功,用户就开始播放视频,造成程序异常,所以在创建成功后才使播放按钮可点击 Log.d("zhangdi","surfaceCreated"); Play.setEnabled(true); }@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.d("zhangdi","surfaceChanged"); }@Override public void surfaceDestroyed(SurfaceHolder holder) {//当程序没有退出,但不在前台运行时,因为surfaceview很耗费空间,所以会自动销毁, // 这样就会出现当你再次点击进程序的时候点击播放按钮,声音继续播放,却没有图像 //为了避免这种不友好的问题,简单的解决方式就是只要surfaceview销毁,我就把媒体播放器等 //都销毁掉,这样每次进来都会重新播放,当然更好的做法是在这里再记录一下当前的播放位置, //每次点击进来的时候把位置赋给媒体播放器,很简单加个全局变量就行了。 Log.d("zhangdi","surfaceDestroyed"); if (player != null) {position = player.getCurrentPosition(); stop(); }}}); }private void play() {Play.setEnabled(false);//在播放时不允许再点击播放按钮 if (isPause) {//如果是暂停状态下播放,直接start isPause = false; player.start(); return; }path = Environment.getExternalStorageDirectory().getPath()+"/"; path = path + et.getText().toString();//sdcard的路径加上文件名称是文件全路径 File file = new File(path); if (!file.exists()) {//判断需要播放的文件路径是否存在,不存在退出播放流程 Toast.makeText(this,"文件路径不存在",Toast.LENGTH_LONG).show(); return; }try {player = new MediaPlayer(); player.setDataSource(path); player.setDisplay(holder);//将影像播放控件与媒体播放控件关联起来 player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Override public void onCompletion(MediaPlayer mp) {//视频播放完成后,释放资源 Play.setEnabled(true); stop(); }}); player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Override public void onPrepared(MediaPlayer mp) {//媒体播放器就绪后,设置进度条总长度,开启计时器不断更新进度条,播放视频 Log.d("zhangdi","onPrepared"); sb.setMax(player.getDuration()); timer = new Timer(); task = new TimerTask() {@Override public void run() {if (player != null) {int time = player.getCurrentPosition(); sb.setProgress(time); }}}; timer.schedule(task,0,500); sb.setProgress(position); player.seekTo(position); player.start(); }}); player.prepareAsync(); } catch (IOException e) {e.printStackTrace(); }}public void play(View v) {play(); Log.d("zhangdi",path); }private boolean isPause; private void pause() {if (player != null && player.isPlaying()) {player.pause(); isPause = true; Play.setEnabled(true); }}public void pause(View v) {pause(); }private void replay() {isPause = false; if (player != null) {stop(); play(); }}public void replay(View v) {replay(); }private void stop(){isPause = false; if (player != null) {sb.setProgress(0); player.stop(); player.release(); player = null; if (timer != null) {timer.cancel(); }Play.setEnabled(true); }}public void stop(View v) {stop(); }@Override protected void onDestroy() {super.onDestroy(); stop(); } }
2.VideoView 系统自带的视频播放控件,自带进度条、暂停、播放等功能,使用起来十分简单,只需要为控件设置好播放路径,监听是否准备就绪,就绪后直接播放就可以了。
效果图
布局代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main2" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.video.Main2Activity" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/et1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:hint="请输入文件名"/> <Button android:id="@+id/btn" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="确定"/> </LinearLayout> <VideoView android:id="@+id/video" android:layout_width="match_parent" android:layout_height="300dp" android:layout_marginTop="10dp"/> </LinearLayout>
完整代码:
package com.example.video; import android.app.Activity; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.MediaController; import android.widget.VideoView; import java.net.URI; public class Main2Activity extends Activity {private VideoView video; private EditText et; private Button btn; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); initView(); }private void initView() {et = (EditText) findViewById(R.id.et1); video = (VideoView) findViewById(R.id.video); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {String path = Environment.getExternalStorageDirectory().getPath()+"/"+et.getText().toString();//获取视频路径 Uri uri = Uri.parse(path);//将路径转换成uri video.setVideoURI(uri);//为视频播放器设置视频路径 video.setMediaController(new MediaController(Main2Activity.this));//显示控制栏 video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Override public void onPrepared(MediaPlayer mp) {video.start();//开始播放视频 }}); }}); } }
3.Vitamio 框架 使用起来和VideoView基本一样,区别在于,我们自己写的和系统自带的控件无法做到所有格式的视频都可以播放,但是这个框架基本可以实现,我用真机测试了mp4,flv,mkv,rmvb,3gp,avi这5中格式的视频,其中只有avi的只有声音没有影像,其他都可以正常播放,不过avi格式无法播放也可能是视频本身有点问题,不过我也没有其他视频了,无法继续测试,如果大家看完文章自己测试的时候可以用,也可以在回复的地方告诉我下,谢了。
vitamio的library下载地址是:https://www.vitamio.org/Download/
效果图与2一样
布局代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main2" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.video.Main2Activity" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/et2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:hint="请输入文件名"/> <Button android:id="@+id/btn1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="确定"/> </LinearLayout> <io.vov.vitamio.widget.VideoView android:id="@+id/video1" android:layout_width="match_parent" android:layout_height="300dp" android:layout_marginTop="10dp"/> </LinearLayout>
完整代码与2也一样,需要注意的是里面的VideoView是Vitamio中的,不是android.widget中的:
package com.example.video; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.Button; import android.widget.EditText; import io.vov.vitamio.MediaPlayer; import io.vov.vitamio.widget.MediaController; import io.vov.vitamio.widget.VideoView; public class Main3Activity extends Activity {private VideoView video; private Button btn; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); initView(); }private void initView() {video = (VideoView) findViewById(R.id.video1); btn = (Button) findViewById(R.id.btn1); et = (EditText) findViewById(R.id.et2); btn.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {String path = Environment.getExternalStorageDirectory().getPath()+"/"+et.getText().toString(); Uri uri = Uri.parse(path); video.setVideoURI(uri); video.setMediaController(new MediaController(Main3Activity.this)); video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Override public void onPrepared(MediaPlayer mp) {video.start(); }}); }}); } }
以上三种方法完整案例demo下载地址:下载地址
Android播放器的三种实现方法相关推荐
- 【安卓】Android播放器的三种实现方法
转载自:http://blog.csdn.net/wozuihaole/article/details/60867076 今天来说一下Android中怎么实现视频播放,我主要说三种: 1.MediaP ...
- android唤醒音乐播放器,android调用音乐播放器,三种方
小弟想请问一下.怎样在自己写的程序中调用系统的音乐播放器呢. 我在google上搜索了.主要是有两种方法,可是都不是我想要的. 第一种是.使用mp3音乐文件的uri.和intent,进行调用.可是这样 ...
- Android 播放视频的三种方式
Android提供了常见的视频的编码.解码机制.使用Android自带的MediaPlayer.MediaController等类可以很方便的实现视频播放的功能.支持的视频格式有MP4和3GP等.这些 ...
- python学习音频-详解python播放音频的三种方法
第一种 使用pygame模块 pygame.mixer.init() pygame.mixer.music.load(self.wav_file) pygame.mixer.music.set_vol ...
- python可以播放音乐吗_详解python播放音频的三种方法
第一种 使用pygame模块 pygame.mixer.init() pygame.mixer.music.load(self.wav_file) pygame.mixer.music.set_vol ...
- Android中XML的三种解析器分析、实战
XML解析器介绍 Android中提供了三种方式来解析XML: SAX(simple API for XML) DOM(文档对象模型) 以及Android内部使用的Pull解析. SAX(simple ...
- Android手机teams,在iOS和Android上自定义Microsoft Teams体验的三种最佳方法
以下是您可以在iOS和Android上自定义Microsoft Teams应用程序以使其成为自己的三种方法 1. 开启黑暗模式,以便iOS和Android上的小组中的消息和其他内容更易于理解和阅读 2 ...
- 计算机音乐播放器设置,Win7系统下设置默认音乐播放器的两种方法
可能很多新手用户不知道Win7系统下怎么设置默认音乐播放器?我们习惯将某一程序设置为默认打开方式,音乐播放器也可以这样子的.一些用户想把酷狗播放器.或者qq音乐设置为默认音乐播放器,只要打开音乐文件, ...
- 用键盘打开计算机管理,windows10系统使用键盘打开设备管理器的三种方法
我们经常都会通过设备管理器,来查看windows10系统中的硬件是否已经正常安装驱动.那么,在鼠标没用的情况下,该如何打开win10设备管理器呢?接下来,系统城小编给大家介绍下没有鼠标直接使用键盘打开 ...
最新文章
- Linux初学(Linux命令行的使用)
- asp.net在线压缩和解压缩的实现
- Android OpenGL ES 离屏渲染(offscreen render)
- 计算机原理课程设计陈宏,东北大学计算机组成基础原理课程教学设计.doc
- Hybris Commerce里的持久层
- vue 新窗口打开外链接
- System.Text.Json 中的字符编码
- mysql两个表查询修改_MySQL:查询、修改(二)
- 各银行汇款手续费之比较
- C语言程序设计 笔试考试,试题样卷
- 回顾2016,工作总结!
- Unity Application Block 1.0系列(7): Lifetime Managers
- stm32呼吸灯程序_STM32裸机开发基础篇02点亮LED
- [原创]手动配置Ubuntu Linux系列3-缺省网关和主机名
- 删除Linux上的用户
- 反洗钱不力,银行遭遇央行15亿天价罚单
- Unity3D 视频教程列表,共 91 套!
- 华为AI Gallery社区《基于机器学习的欧洲杯赛事预测》技术分析系列——(一)基本原理
- 【畅购商城】购物车模块之添加购物车
- c语言gl函数,R语言:gl()函数
热门文章
- [转]给所有女孩子们的话
- 人工神经网络应用领域,人工神经网络应用范围
- 2017用计算机侦探剧,2017年最火爆的十部网剧,你看过几部?
- 特征提取(Feature Detect)、特征描述(Feature Descriptor)、特征匹配(Feature Match)
- word中编号怎么转成普通的字,如何把WORD编号转为普通文本
- Iphone使用mac的无线网热点直接使用(可以用来借用vpn)
- 关于IIS7.0(Internet Information Services)的特性和配置
- Middleware【中间件】简介
- 0字节文件无法删除的解决办法
- EDM营销邮件规范-制作-设计-参考资料