Android播放视频有好几种方式,比如VideoView,SurfaceView,Android自带的播放器,第三方播放器(比如vitamio等等 之前毕设用过,挺不错)
公司需要编写相关的测试代码,简单研究了一下。做做笔记,备忘。(注:部分代码来源于互联网)

使用VideoView播放视频:

布局文件:很简单,VideoView+几个button,用线性布局简单控制一下

<LinearLayout 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"android:orientation="vertical"tools:context=".MainActivity" ><VideoView
        android:id="@+id/videoview"android:layout_width="fill_parent"android:layout_height="200dp" /><LinearLayout
        android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><Button
            android:id="@+id/play"android:text="play"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><Button
            android:id="@+id/pause"android:text="pause"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><Button
            android:id="@+id/replay"android:text="replay"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /></LinearLayout></LinearLayout>

继续操作之前,先在SD卡根目录放置一个视频文件1.mp4(先使用固定路径,之后再使用动态设置的路径)
下面继续写MainActivity:

public class MainActivity extends Activity implements OnClickListener {private static final String TAG = "MainActivity";VideoView video;Button play;Button pause;Button replay;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);video = (VideoView) findViewById(R.id.videoview);play = (Button) findViewById(R.id.play);pause = (Button) findViewById(R.id.pause);replay = (Button) findViewById(R.id.replay);play.setOnClickListener(this);pause.setOnClickListener(this);replay.setOnClickListener(this);logcat("onCreate");initVediopath();}@Overrideprotected void onDestroy() {super.onDestroy();if (null != video) {video.suspend();}}private void initVediopath() {logcat("initVediopath");File file = new File(Environment.getExternalStorageDirectory(), "1.mp4");logcat("" + Environment.getExternalStorageDirectory());if (file.exists()) {logcat("setPath");video.setVideoPath(file.getPath());} else {Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();logcat("file not exsit");}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.play:if (!video.isPlaying()) {video.start();}break;case R.id.pause:if (video.isPlaying()) {video.pause();}break;case R.id.replay:if (video.isPlaying()) {video.resume();}break;default:break;}}public void logcat(String log) {Log.i(TAG, log);}
}

MainActivity也很简单,findv的iew,设置listener,设置视频路径,Activity销毁时将VideoView挂起。按钮 的点击事件也就简单的调用VideoView的相关方法。
最后别忘了添加读取SD卡的权限

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

使用 SurfaceView+MediaPlayer播放视频

MediaPlayer控制视频,SurfaceView负责显示(个人理解,有误请帮忙指出,另外此部分代码大部分参考某篇博客,但是暂时找不到原文了。。。)
布局文件:和上面类似,不过把VideoView换成SurfaceView,另外多了几个button

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/LinearLayout1"android:layout_width="match_parent"android:layout_height="match_parent"android:weightSum="1"android:orientation="vertical" ><SurfaceViewandroid:id="@+id/surfaceVIew"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="0.15"tools:context=".MainActivity" /><LinearLayout android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="0.85"><Button android:id="@+id/btn_play"android:text="开始"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Button android:id="@+id/btn_pause"android:text="暂停"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Button android:id="@+id/btn_stop"android:text="停止"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Button android:id="@+id/btn_low"android:text="调低"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Button android:id="@+id/btn_hight"android:text="调高"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>
</LinearLayout>

与上面一样,先使用死路径,在SD卡根目录放置1.mp4。同时先把访问SD卡的权限加上吧。

主Activity:
和上面的步骤类似,不过稍微复杂些。主要是SurfaceView有三个callback
surfaceCreated
surfaceChanged
surfaceDestroyed
在SurfaceView创建时做一些视频的初始化操作。
在SurfaceView销毁时释放资源
横竖屏的地方暂时可以忽略。大体上和上面还是一样的。

public class MainActivity extends Activity implements OnClickListener {/* 功能按钮 */private Button btn_play, btn_pause, btn_stop, btn_low, btn_height;/* SurfaceView */private SurfaceView mSurfaceView;/* 播放视频对象 */private MediaPlayer mediaPlayer;/* 系统声音 */private AudioManager audioManager;/* 记录播放位置 */private int position;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);/* 设置窗口无title */requestWindowFeature(Window.FEATURE_NO_TITLE);/* 全屏显示 */this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.activity_main);findViews();setListeners();mediaPlayer = new MediaPlayer();setSurfaceView();}// 横竖屏切换时的处理@Overrideprotected void onSaveInstanceState(Bundle outState) {if (mediaPlayer != null && mediaPlayer.isPlaying()) {// 如果在播放的时候切换屏幕则保存当前观看的位置outState.putInt("position", mediaPlayer.getCurrentPosition());}super.onSaveInstanceState(outState);}// 横竖屏切换后的处理@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {if (savedInstanceState.containsKey("position")) {position = savedInstanceState.getInt("position");// 取得切换屏幕时保存的位置}super.onRestoreInstanceState(savedInstanceState);}/* 实例化UI */private void findViews() {btn_play = (Button) findViewById(R.id.btn_play);btn_pause = (Button) findViewById(R.id.btn_pause);btn_stop = (Button) findViewById(R.id.btn_stop);btn_low = (Button) findViewById(R.id.btn_low);btn_height = (Button) findViewById(R.id.btn_hight);mSurfaceView = (SurfaceView) findViewById(R.id.surfaceVIew);audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);}/* 为5个按钮设置监听 */private void setListeners() {btn_play.setOnClickListener(this);btn_pause.setOnClickListener(this);btn_stop.setOnClickListener(this);btn_low.setOnClickListener(this);btn_height.setOnClickListener(this);}/* 播放视频 */private void playMedia() {/* 初始化状态 */mediaPlayer.reset();/* 设置声音流类型 */mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);/* 设置mp3\mp4加载路径 */File file = new File(Environment.getExternalStorageDirectory(), "1.mp4");try {mediaPlayer.setDataSource(file.getAbsolutePath());// 缓冲mediaPlayer.prepare();// 开始播放mediaPlayer.start();// 具体位置Log.i("position", position + "------");mediaPlayer.seekTo(position);// 视频输出到ViewmediaPlayer.setDisplay(mSurfaceView.getHolder());// 重置位置为0position = 0;} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/* 设置surfaceView视图 */private void setSurfaceView() {// creates a "push" surfacemSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 设置事件,回调函数mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {/* SurfaceView创建时 */@Overridepublic void surfaceCreated(SurfaceHolder holder) {if (position > 0) {playMedia();position = 0;}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format,int width, int height) {}/* SurfaceView销毁视图 */@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {if (mediaPlayer.isPlaying()) {mediaPlayer.stop();}/* Activity销毁时停止播放,释放资源。不做这个操作,即使退出,还是能听到视频的声音 */mediaPlayer.release();}});}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_play:// 播放if (mediaPlayer != null && mediaPlayer.isPlaying()) {return;} else {playMedia();}break;case R.id.btn_pause:// 暂停if (mediaPlayer != null && mediaPlayer.isPlaying()) {position = mediaPlayer.getCurrentPosition();mediaPlayer.pause();} else {return;}break;case R.id.btn_stop:// 停止if (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.stop();position = 0;} else {return;}break;case R.id.btn_low:// 调小音量// 获取当前的音乐音量int volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);Log.v("Volume", "volume" + volume);// 音量>0if (volume > 0) {audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_LOWER, 0);} else {return;}break;case R.id.btn_hight:// 调大音量volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);// 音量<100if (volume < audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) {audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_RAISE, 0);} else {return;}break;}}}

下一篇说下如何扫描SD卡的视频文件,并会附上本文中的案例和一个播放MP3的demo

Android 播放SD卡视频 Demo相关推荐

  1. android 获取sd卡视频文件名,android – 如何获取SD卡上的视频列表

    查询MediaStore内容提供商 一个例子可能是 public static void printNamesToLogCat(Context context) { Uri uri = MediaSt ...

  2. Android 扫描SD卡中的所有视频文件

    Android应该是已经把所有的视频文件音频都在开机时,扫描完毕然后存在本地SQLite数据库了,因此,我们"扫描"的最简单方法是读取这个已经存储好的数据库.但是这样做,在程序开启 ...

  3. android读写sd卡代码,android读写SD卡中的文件 demo

    有时,我们需要将更大的文件保存下来,就不能用手机内置的存储空间,毕竟是有限的,所以将文件保存在SD卡中. 要读写SD卡,首先要知道手机上是否有SD卡,且是否可读写 String str = " ...

  4. Android播放器实现视频窗口实时放大缩小功能

    很多开发者希望Android播放端实现视频窗口的放大缩小功能,为此,我们做了个简单的demo,通过播放端回调RGB数据,直接在上层view操作处理即可,Github:https://github.co ...

  5. Android 判断SD卡是否存在及容量查询

    转载:http://blog.csdn.net/xinzheng_wang/article/details/7827775 Android 判断SD卡是否存在及容量查询的简单方法如下: 首先要在And ...

  6. Android 获取SD卡路径和判断SD卡是否存在.

    android获取sd卡路径方法: public String getSDPath(){ File sdDir = null; boolean sdCardExist =Environment.get ...

  7. videojs播放m3u8后缀视频Demo

    videojs播放m3u8后缀视频Demo 转载自:https://segmentfault.com/a/1190000024447688 <!DOCTYPE html><html ...

  8. 2011 明锐 CD 大众收音机 播放SD 卡顿问题

    2011 明锐 CD 大众收音机 播放SD 卡顿问题 TOPPOWER生产型号1ZD 085 186 在手动或自动切换歌曲时会随机出现反复回放上首歌的部分内容,有时会出现报sd err 错误无法播放或 ...

  9. sd卡视频被删怎么恢复呢?

    在移动互联网中,经常是以视频为主记录着我们生活的方方面面.随着视频文件的增多,储存也成为了新的问题.虽然在相机SD卡有一定存储空间,但往往很容易损坏.所以不少小伙伴会选择在电脑上进行备份储存.由于空间 ...

最新文章

  1. 网格员计算机基本操作,网格交易总结系列(一)基本操作篇
  2. 剑指offer十:矩形覆盖
  3. JavaScript: 代码简洁之道
  4. 1.9 Java 9增强的自动资源管理
  5. Nginx Mac笔记
  6. JavaFx实现-渐变效果之一
  7. 协作通信-af df的matlab仿真,协作通信-AF、DF的MATLAB仿真(解压密码yuema1086)
  8. LINQ之路 2:C# 3.0的语言功能(上)
  9. curl有php内存缓存,PHP CURL内存泄露的解决方法
  10. 张小龙:做 PC 版微信是一种破坏,本来不想做
  11. 目标检测——neck组件的学习笔记
  12. C#常见算法题目(面试准备)
  13. UDP和TCP 简单 区别
  14. 查询优化器内核剖析第六篇:谈谈Join的顺序问题,纠正江湖偏方
  15. 微信小程序实现OCR扫描识别
  16. Stata: 图示交互效应\调节效应
  17. 文件服务器 excle 变为temp,WPS的excel表格保存之后变成tmp_共享文档无法保存EXCLE 生成TMP...
  18. Tableau自定义分类调色板
  19. 银河麒麟V10 SP2 搭建tftp服务
  20. 苹果隐藏app_iOS14隐藏功能,很实用!附部分BUG解决方案

热门文章

  1. mysql操作json优点和缺点_mysql之使用json
  2. Luogu P1197 [JSOI2008]星球大战
  3. [bzoj 3594] [Scoi2014]方伯伯的玉米田
  4. ASP.NET关于WebPages的一点总结
  5. android fragment点击返回键实现内容切换?
  6. zz 聊聊并发(二)
  7. leetcode 1160 python
  8. 深度学习——行数据的分拆及如何“喂”给训练过程
  9. 资源放送丨《Oracle RAC 集群安装部署》PPT视频
  10. 详解PostgreSQL数据库中的两阶段锁