Android多媒体之视频播放器高级开发
1.获取播放的数据源
播放视频的数据源一般有两个,一个是请求网络,从服务器后台直接获取播放的视频信息,另一种是播放手机中本地的视频,这里我们采用的播放源为播放手机本地的视频
1.1 查询获取手机中的视频的信息
1.1.1 查询方法一
定义要查询到的视频的信息,包括视频的名称,视频大小,视频播放时长以及在手机中的储存位置
String[] projection = {Media._ID,Media.TITLE,Media.SIZE,Media.DURATION,Media.DATA};
进行数据的查询操作
Cursor cursor = getActivity().getContentResolver().query(Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
这里查询到的信息是包含在cursor对象中的
1.1.2 查询方法二
SimpleQueryHandler queryHandler = new SimpleQueryHandler(getActivity().getContentResolver());String[] projection = {Media._ID,Media.TITLE,Media.SIZE,Media.DURATION,Media.DATA};queryHandler.startQuery(0, adapter, Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
public class SimpleQueryHandler extends AsyncQueryHandler{public SimpleQueryHandler(ContentResolver cr) {super(cr);}@Overrideprotected void onQueryComplete(int token, Object cookie, Cursor cursor) {super.onQueryComplete(token, cookie, cursor);if(cookie!=null && cookie instanceof CursorAdapter){CursorAdapter adapter = (CursorAdapter) cookie;adapter.changeCursor(cursor);//相当于notify}}}
边里是调用的异步查询的方法,查询到的视频的相关信息也是包含在cursor中的,其中传入的adapter对象是继承于CursorAdapter
1.1.3 建立保存视频信息的info对象
public class VideoItem implements Serializable{public String title;//视频的名称public long size;//视频的大小public long duration;//视频的时长public String path;//视频在手机中的路径/*** 将cursor中的数据封装为一个info* @param cursor* @return*/public static VideoItem fromCursor(Cursor cursor){VideoItem videoItem = new VideoItem();videoItem.duration=cursor.getLong(cursor.getColumnIndex(Media.DURATION)));videoItem.path=cursor.getString(cursor.getColumnIndex(Media.DATA)));videoItem.size=cursor.getLong(cursor.getColumnIndex(Media.SIZE)));videoItem.title=cursor.getString(cursor.getColumnIndex(Media.TITLE)));return videoItem;}}
2.以列表的方式将视频信息显示出来
2.1 创建数据适配器
这里使用到的是ListView来设置显示数据,所以需要给ListView准备一个适配器,来设置显示数据,由于我们查询到的数据是封装在Cursor中的,所以我们这里可以创建继承于CursorAdapter的适配器
public class VideoListAdapter extends CursorAdapter{public VideoListAdapter(Context context, Cursor c) {super(context, c);}/*** 直接从布局中加载view返回,这里就是ListView中显示的item布局,可以自定义随便布局*/@Overridepublic View newView(Context context, Cursor cursor, ViewGroup parent) {return View.inflate(context, R.layout.adapter_video_list, null);}ViewHolder holder;/*** 将数据设置给view*/@Overridepublic void bindView(View view, Context context, Cursor cursor) {holder = getHolder(view);//获取数据,这里的数据是保存在cursor中,通过方法fromCursor直接转换成VideoItem对象保存的信息VideoItem videoItem = VideoItem.fromCursor(cursor);holder.tv_title.setText(videoItem.title);//这里获取到的时长是毫秒,可以通过 自定义的时间格式来对时间进行格式化操作holder.tv_duration.setText(StringUtil.formatVideoDuration(videoItem.duration()));//将视频的大小格式化为M来进行数据显示holder.tv_size.setText(Formatter.formatFileSize(context, videoItem.size()));}private ViewHolder getHolder(View view){ViewHolder viewHolder = (ViewHolder) view.getTag();if(viewHolder==null){viewHolder = new ViewHolder(view);view.setTag(viewHolder);}return viewHolder;}class ViewHolder{TextView tv_title,tv_duration,tv_size;public ViewHolder(View view){tv_title = (TextView) view.findViewById(R.id.tv_title);tv_duration = (TextView) view.findViewById(R.id.tv_duration);tv_size = (TextView) view.findViewById(R.id.tv_size);}}}
2.2 为ListView设置显示数据
VideoListAdapter adapter = new VideoListAdapter(getActivity(), null);listView.setAdapter(adapter);
注:到这里,我们就 可以将手机中的视频的信息显示到一个ListView中了
3.点击信息条目,跳转到视频播放页面
3.1 为ListView设置条目的点击事件,并获取到相应位置的视频信息
listView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//获取当前点击的条目对应的数据Cursor cursor = (Cursor) adapter.getItem(position);Bundle bundle = new Bundle();//当前点击播放视频的位置bundle.putInt("currentPosition", position);//视频信息的集合bundle.putSerializable("videoList", cursorToList(cursor));Intent intent = new Intent(getActivity(),VitamioPlayerActivity.class);intent.putExtras(bundle);getActivity().startActivity(intent);}});
其中调用了一个方法,是将cursor中的数据转换成集合中保存对象的方法保存信息,以方便数据的传递
private ArrayList<VideoItem> cursorToList(Cursor cursor){ArrayList<VideoItem> list = new ArrayList<VideoItem>();cursor.moveToPosition(-1);while(cursor.moveToNext()){list.add(VideoItem.fromCursor(cursor));}return list;}
其中调用的VideoItem.fromCursor方法是对象中封装的转换cursor对象数据的方法
4.视频播放页面
4.1 获取传递过来的视频信息
private int currentPosition;//当前播放视频的位置private ArrayList<VideoItem> videoList;//当前的视频列表currentPosition = getIntent().getExtras().getInt("currentPosition");videoList = (ArrayList<VideoItem>) getIntent().getExtras().getSerializable("videoList");
4.2 设置视频播放并设置监听
这里使用到的是控件VideoView,
//设置播放的数据playVideo();//设置进行播放的操作监听video_view.setOnPreparedListener(new OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {//进行视频的播放 video_view.start();//更新视频播放指示的进度条updatePlayProgress();//设置指示的进度条的最大值video_seekbar.setMax((int) video_view.getDuration());//设置显示当前的播放时间tv_current_position.setText("00:00");//设置显示视频的总时长tv_duration.setText(StringUtil.formatVideoDuration(video_view.getDuration()));//设置播放按钮的背景图片btn_play.setBackgroundResource(R.drawable.selector_btn_pause);}});
调用的方法playVideo
private void playVideo(){//上一视频的控制按钮(如果是第一节,则不再点击)btn_pre.setEnabled(currentPosition!=0);//下一视频的控制按钮(如果是最后一节,则不再点击)btn_next.setEnabled(currentPosition!=(videoList.size()-1));//获取当前位置对应的数据VideoItem videoItem = videoList.get(currentPosition);//设置页面显示的视频标题tv_name.setText(videoItem.getTitle());//进行视频的播放video_view.setVideoURI(Uri.parse(videoItem.getPath()));}
playVideo方法为videoview设置了播放的数据源,当videoView加载准备好后,由于设置了监听OnPreparedListener方法,所以会调用其中的onPrepared,在这里进行开始播放视频的操作,并可以获取到当前要播放的视频的总时长,以设置指示进度的进度条显示的最大值,以及更新其他相关的UI等
4.3 设置点击播放上一节视频的方法
btn_pre.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if(currentPosition>0){currentPosition - -;playVideo();}}});
btn_pre 是播放上一节视频的触发按钮
这里的currentPosition是当前播放的视频在视频集合中的位置,调用playVideo,会将对应位置的视频信息获取出来,然后设置给VideoView,然后当资源准备完成后,会调用到监听OnPreparedListener中的onPrepared方法,来进行相应的视频播放
4.4 设置点击播放下一节视频的方法
btn_next.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if(currentPosition<(videoList.size()-1)){currentPosition ++;playVideo();}}}});
btn_next是播放下一节视频的触发按钮,播放原理逻辑与播放上一节视频内容是一致的
4.5 为播放视频设置其他的相监听
//当视频播放完成时进行的操作监听
video_view.setOnCompletionListener(new OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {//例如可以更新播放进度的指示大小,以及其他相关的UI操作}});
//视频缓冲进度的监听video_view.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) {//percent:0-100long bufferProgress = (long) ((video_view.getDuration()/100f)*percent);//这里设置显示视频缓冲进度条的显示 video_seekbar 是指示视频播放的进度条video_seekbar.setSecondaryProgress((int) bufferProgress);}});
//视频播放卡顿时进行的操作video_view.setOnInfoListener(new OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {switch (what) {case MediaPlayer.MEDIA_INFO_BUFFERING_START ://开始卡顿 显示缓冲加载的进度条ll_buffer.setVisibility(View.VISIBLE);break;case MediaPlayer.MEDIA_INFO_BUFFERING_END ://卡顿结束 隐藏缓冲加载的进度条ll_buffer.setVisibility(View.GONE);break;}return true;}});
//视频播放错误的监听video_view.setOnErrorListener(new OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {switch (what) {case MediaPlayer.MEDIA_ERROR_UNKNOWN ://未知格式,视频文件错误,进行相关信息的提示Toast.makeText(VitamioPlayerActivity.this, "视频格式不支持", 0).show();break;}return true;}});}
4.6 对播放中指示播放进度的进度条(video_seekbar)的操作
4.6.1 指示缓存进度的操作
在setOnBufferingUpdateListener这个监听中操作了video_seekbar的缓存进行更新
4.6.2 实时更新播放的指示进度
private void updatePlayProgress(){//显示当前的播放进度tv_current_position.setText(StringUtil.formatVideoDuration(video_view.getCurrentPosition()));//设置进度条的指示位置video_seekbar.setProgress((int) video_view.getCurrentPosition());handler.sendEmptyMessageDelayed(1, 500);}private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {switch (msg.what) {case 1:updatePlayProgress();break;};};
可以看到,这里使用的是handler消息机制,循环发送消息
4.6.3 手动拖动进度条控制视频播放的进度
video_seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){//fromUser =true;表示是用户手动拖动//播放相应位置的视频video_view.seekTo(progress);//更新播放时间进度显示tv_current_position.setText(StringUtil.formatVideoDuration(progress));}}});
4.7 对播放中指示播放音量的进度条操作
4.7.1 初始化显示系统的音量
private AudioManager audioManager;
private int currentVolume;//系统音乐和视频类型当前的音量
private boolean isMute = false;//是否是静音模式
private int maxVolume;//系统中音乐和视频类型最大音量
private SeekBar voice_seekbar;//显示音量指示信息的进度条private void initVolume(){audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);//maxVolume:0-15 maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);//设置音量指示进度条的最大指示进度voice_seekbar.setMax(maxVolume);//设置当前的音量大小对应的指示进度显示voice_seekbar.setProgress(currentVolume);}
voice_seedbar 是视频页面指示播放音量大小的进度条
4.7.2 手动拖动进度条改变播放音量的大小
与拖动指示播放进度的进度条的方法一致
voice_seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){//表示是用户手动拖动isMute = false;//记录当前的音量currentVolume = progress;//更新系统音量的操作updateSystemVolume();}}});
/*** 更新系统音量*/private void updateSystemVolume(){if(isMute){//静音模式,设置音量大小为0,并将指示音量大小的进度条进度设置为0audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);voice_seekbar.setProgress(0);}else {//设置当前改变到的音量大小的进度voice_seekbar.setProgress(currentVolume);//第三个参数如果是1,会显示音量改变的浮动面板audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);}}
4.7.3 手动上下滑动屏幕改变播放音量的大小
涉及到手势操作,做一些初始化操作准备
int touchSlop = ViewConfiguration.getTouchSlop();GestureDetector gestureDetector = new GestureDetector(this,new MyOnGestureListner());
可以在相关方法中做一些滑动过程中的操作
private class MyOnGestureListner extends SimpleOnGestureListener{@Overridepublic void onLongPress(MotionEvent e) {super.onLongPress(e);}@Overridepublic boolean onDoubleTap(MotionEvent e) {return super.onDoubleTap(e);}@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {return super.onSingleTapConfirmed(e);}}
捕捉触摸事件,并将事件传递给gestureDetector;
private float downY;@Overridepublic boolean onTouchEvent(MotionEvent event) {gestureDetector.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:downY = event.getY();break;case MotionEvent.ACTION_MOVE:float moveY = event.getY();float moveDistance = moveY - downY;//对滑动距离进行一个值的限制if(Math.abs(moveDistance)<touchSlop)break;isMute = false;float totalDistance = Math.min(screenHeight, screenWidth);float movePercent = Math.abs(moveDistance)/totalDistance;int moveVolume = (int) (movePercent*maxVolume);//这个值一定是0if(moveDistance>0){//减小音量currentVolume -= 1;}else {//增大音量currentVolume += 1;}updateSystemVolume();downY = moveY;break;case MotionEvent.ACTION_UP:break;}return super.onTouchEvent(event);}
Android多媒体之视频播放器高级开发相关推荐
- android多媒体视频,android多媒体(视频播放器)
##视频处理 一丶VideoView控件 点击创建一个播放器并播放视频 /** * 播放视频 * @param view */ public void play(View view){ vv.setV ...
- 开源安卓Android流媒体音视频播放器实现声音自动停止、恢复、一键静音功能源码
本文转自EasyDarwin团队John的博客:http://blog.csdn.net/jyt0551/article/details/60802145 我们在开发安卓Android流媒体音视频播放 ...
- android系统更新视频播放器,基于的Android系统地视频播放器.doc
本科毕业设计(论文) 基于Android系统的视频播放器Through the implementation of video player based on Android platform 致 谢 ...
- android 实现视频播放功能,Android项目实现视频播放器
本文实例为大家分享了Android项目实现视频播放器的具体代码,供大家参考,具体内容如下 VideoView控件是播放视频用的,借助它可以完成一个简易的视频播放器. ①在activity_main.x ...
- 手机上的android版本下载视频播放器,ZZPlayer手机版下载
软件标签: 视频播放器 ZZPlayer是一款视频播放器,支持多种播放格式,也是猪猪影院专用播放器基于准视频点播内核的多功能.个性化的播放器软件.且所有的操作都可以直接在屏幕上完成,兼容性做得非常不错 ...
- Android学习6——视频播放器
一.学习目标 1.综合应用课程知识. 2.掌握 App 开发流程及相关工具. 3.设计一个基于 Android 平台的简单视频播放器. 二.环境 1.JDK-15.0.2 以上 2.Android S ...
- 基于智能手机Android平台音乐播放器全程开发实战
基于android开发的智能手机平台的应用越来越多,目前也是一块比较热门的技术,本项目为基于android系统的音乐播放器项目,学习本项目的目的是为了让学员尽快掌握android领域的小应用的开发.项 ...
- android ios 传视频播放器,推荐用于iOS / Android全面格式的视频播放器|手机最强大的播放器...
几天前,一个朋友以ts格式下载了一些高清电视剧,但是无法在iPad上播放,因此我想在计算机上将其转换为MP4格式. 花了时间和精力,结果并不令人满意. 事实上手机上的万能播放器,所有平台现在都具有支持 ...
- Android MediaPlayer本地视频播放器
该文章的目的是,让初学者能够快速掌握一个简单的本地视频播放器.该Demo中用到了SurfaceView.MediaPlayer. 实现效果图: <RelativeLayout xmlns:and ...
最新文章
- 封装一个计时器,记录页面的停留时间
- GAN独领风骚!盘点2021最惊艳38篇AI论文
- heartbeat v2版CRM的高可用web集群的实现
- 调制优缺点_复合铝基润滑脂和普通润滑脂的区别,复合铝基脂有什么优缺点
- Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式
- Decorator(装饰)--对象结构型模式
- IPMITool driver
- binlog日志_mysql 重要日志文件总结
- Sublime Text 3 搭建Python3 IDE
- 联想90W快充是假的吗?官方回应:我们不玩文字游戏
- 人民网舆情:公众对网约车或存偏见
- linux内核进程抢占,Re: Linux中进程能否被抢占
- java服务器端socket,java 服务器端socket
- RabbitMQ 交换机、队列、消息持久化
- win10家庭版和专业版的区别
- excel多元线性拟合_[求助]excel里面的linest函数中多元回归怎么用啊?
- DNW5.0 USB 不OK
- 华为事件对我们个人成功的启示:为什么自强自立不是出路?
- 自己组装nas服务器万兆,万兆网络、装M.2 SSD的NAS服务器
- 修改图片exif信息
热门文章
- 分布式训练PyTorch 源码解读
- 干货收藏!639页《深度学习:Deep Learning》图文并茂课程PPT
- 《Python编程从入门到实践》记录之测试代码(unitttest模块)
- 表格数据画图神器-pandas画图操作
- 从零开始编写深度学习库(五)ConvolutionLayer CPU编写
- 关于国土空间规划的价值的一些思考
- 陈常青老师的讲座的笔记
- 计算机考试的基础知识高考,计算机考试基础知识试题..doc
- 安卓怎么把一个按钮设计成梯形_电气控制电路与PLC之间的梯形图转化,挺实用!...
- DBeaver 导出EXCEL文件