Android多媒体详解
先看一下效果图
1、 MediaPlayer播放音频
2、 SoundPool播放音频
3、 VideoView播放视频
4、 通过Intent意图调用自带视频播放器
5、 MediaPlayer和SurfaceView播放视频
1、MediaPlayer播放音频
MediaPlayer是用于播放音频和视频的,来看一下MediaPlayer类控制音频的常用方法
setDataSource() |
设置要播放的音频文件的位置 |
prepare() |
在播放之前调用这个方法完成准备工作 |
start() |
开始或继续播放音频 |
pause() |
暂停播放音频 |
reset() |
将MediaPlayer对象重置到刚刚创建的状态 |
seekTo() |
从指定位置开始播放音频 |
stop() |
停止播放音频 |
relase() |
释放掉与MediaPlayer对象相关的资源 |
isPlaying() |
判断当前MediaPlayer是否正在播放音频 |
getDurtion() |
获取载入的音频文件的时长 |
接下来看一下MediaPlayer的具体使用步骤:
1、创建MediaPlayer
MediaPlayer mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManger.STREAM_MUSIC);//设置声音流的类型
MediaPlayer接收的声音类型有如下几种:
l AudioManger.STREAM_MUSIC:音乐
l AudioManger.STREAM_RING:铃声
l AudioManger.STREAM_ALARM:闹钟
l AudioManger.STREAM_NOTIFICTION:提示音
2、设置数据源
设置数据源的方式有三种,分别是设置播放应用自带的音频文件、设置播放SD卡中的音频文件、设置播放网络音频文件。具体代码如下:
//播放应用res/raw目录下的自带的音频文件
mediaPlayer.create(this,R.raw.xxx);
//播放SD卡中的音频文件
mediaPlayer.setDataSource(“mnt/sdcard/xxx.mp3”);
//播放网络音频文件
mediaPlayer.setDataSourse(“http://www.xxx.mp3”);
3、播放音乐
播放本地音乐文件与播放网络文件有所不同,当播放本地文件时使用的是prepare();方法通知底层框架准备播放音乐,而准备播放网络音频文件使用prepareAsync()方法。具体代码如下:
//播放本地文件
mediaPlayer.prepare();
mediaPlayer.start();
//播放网络文件
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(newOnPreparedListener() {@Overridepublic void onPrepared(MediaPlayermediaPlayer) {// TODO 自动生成的方法存根mediaPlayer.start();}});
注意:当播放网络中的文件时,需要添加网络访问权限
<uses-permission android:name="android.permission.INTERNET"/>
Prepare()与PreoareAsync()的区别:
l Prepare()是同步操作,在主线程中执行,它会对音频文件进行解码,当prepare()执行完毕之后才会继续向下执行。
l prepareAsync()是子线程中执行的异步操作,不管它有没有执行完成都不音响主线程的执行操作。但是,如果音频文件没有解码完毕就执行start()方法会播放失败。因此这里这里要监听音频准备好的监听器OnPreparedListener()。当音频解码完成可以播放时会执行OnPreparedListener()中的onPrepared()方法,在该方法中执行播放音乐的操作即可。
2、SoundPool播放音频
在游戏开发中经常需要播放一些游戏音效(比如爆炸声、物体撞击声等),这些音效的共同特点就是短促、密集、延迟程度小。在这种情况下可以使用SoundPool代替MediaPlayer来播放这些音效。下面分步骤讲解如何使用SoundPool播放音效:
1、创建SoundPool对象
在创建SoundPool对象时可以使用它的构造方法,该方法有三个参数
SoundPool soundPool=new SoundPool(int maxStreams, int streamType,int srcQuality);
l maxStreams:同时播放的流的最大数量。
l streamType:流的类型,一般为AudioManger.STREAM_MUSIC:音乐。
l srcQuality采样转化率质量,当前无效可以使用0作为默认值。
2、将多个声音添加到Map中
创建好SoundPool对象后需要添加音乐文件,音乐文件素材放在res/raw目录下或assets目录下。一般多个声音添加到一个Map中,具体代码如下:
SoundPoolsoundPool=new SoundPool(maxStreams, streamType,srcQuality);Map<Integer, Integer> map=new HashMap<Integer, Integer>();map.put(0, soundPool.load(this, R.raw.dingdong, 1));map.put(1,soundPool.load(this, R.raw.bang, 1));
soundPool.load()方法是为soundPool对象添加音乐文件,其中第三个参数表示文件加载的优先级。
3、VideoView播放视频
播放视频文件与播放音频文件类似,只是,视频的播放需要视觉组件将影像显示出来。在Android中主要使用VideoView和SurfaceVIew播放视频,其中VIdeoVIew组件播放视频最为简单,它将视频的显示和控件集于一身,由于VideoView的用法和MediaPlayer类似,其中提供的常用方法就不一一介绍了,其中setVideoPath():设置要播放的视频文件的位置需要知道。
具体步骤如下:
1、 创建VideoView
不同于音乐播放器,视频播放器需要在界面上显示,因此首先要在布局文件中创建VideoView控件
<VideoViewandroid:id="@+id/videoView1"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
2、 视频播放
使用VideoView播放视频和音频一样,既可以本地播放,也可以播放网络中的视频,具体代码如下:
VideoViewvideoView=(VideoView) findViewById(R.id.videoView1);//播放本地视频videoView.setVideoPath("mnt/sdcard/b.avi");//加载网络视频videoView.setVideoURI("http://www.xxx.avi");
videoView.start();
注意:播放网络视频时需要添加网络访问权限
<uses-permission android:name="android.permission.INTERNET"/>
这里上传一下代码:
import android.app.Activity;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.widget.MediaController;
import android.widget.VideoView;public class Video extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.video);VideoView vv = (VideoView) findViewById(R.id.videoView1);MediaController mc=new MediaController(this);//设置默认控制器,里面自带暂停,快进,播放mc.setBackgroundColor(Color.YELLOW);vv.setMediaController(mc);//讲控制器添加到VideoView中去Uri data=Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath()+"/auqi.3gp");vv.setVideoURI(data);vv.start();}
}
3、 为VideoView添加控制器
使用VideoView播放视频时可以为他添加一个控制器或媒体播放器MediaController,它是一个包含媒体播放器(MediaPlayer)控件的视图。它自带播放按钮,如播放、暂停、倒带、快进与进度滑动器
MediaController controller=new MediaController(context);
videoView.setMediaController(controller);//为VideoView绑定控制器
4、通过Intent意图调用自带视频播放器
利用Intent只是调用系统自带的视频播放器
Intent intent=new Intent(android.content.Intent.ACTION_VIEW);Uri uri=Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath()+"/auqi.3gp");intent.setDataAndType(uri, "video/3gp");//注意这个Type是由文件类型(video)和播放的格式(3gp)所组成startActivity(intent);
5、MediaPlayer和SurfaceView播放视频
当开发者需要根据需求自定义视频播放器的时候,使用VideoVIew就会很麻烦。为此,Android系统中还提供另一种播放视频的方式,就是MediaPlayer和Surface结合使用。MediaPlayer可以播放视频,只不过它在播放视频时没有图像输出(注意这句话),因此需要使用SurfaceVIew组件。
SurfaceVIew是继承自View用于显示图像的组件。SurfaceVIew最大的特点就是它的双缓冲技术,所谓的双缓冲就是在它的内部有两个线程,例如A线程和B线程。当线程A更新界面时,线程B进行后台技术操作,当两个线程都完成各自的任务时,它们会互相交换,两个线程就这样无限循环交替更新和计算。由于SurfaceVIew这种特性可以避免画图任务繁重而造成的主线程的阻塞,从而提高了程序的反应速度,因此在游戏开发中多用SurfaceVIew,例如游戏中的背景、人物、动画等
1、创建SurfaceVIew控件
SurfaceVIew是一个控件,使用时需要在布局文件中定义
<SurfaceViewandroid:id="@+id/surfaceView1"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
2、获取界面显示容器并设置类型
布局创建好之后,在代码中找到控件并得到SurfaceVIew的容器SurfaceHolder
具体代码如下:
SurfaceView view = (SurfaceView)findViewById(R.id.surfaceView1);SurfaceHolder holder=view.getHolder();holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
是一个接口类型,就是一个容器,通过SurfaceHolder对象控制SurfaceView的大小和像素格式,监控控件中的内容格式
在这里添加SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS参数为的是不让SurfaceView自己维护双缓冲区,而是交给MediaPlayer底层去管理。虽然该API已经过时了,但是在Android4.0版本以下的系统中必须添加该参数
注意播放视频是MediaPlayer框架
3、为SurfaceView添加回调
如果onCreate()方法执行时,SurfaceView还没有完全创建好。这时候播放视频会出现异常,因此,需要添加SurfaceHolder的回调函数CallBack,在SurfaceCreated()方法中执行视频的播放
CallBack接口一共有三个回调方法:
l surfaceChanged():SurfaceView的大小发生变化
l surfaceCreated():SurfaceView的holder被创建
l surfaceDestroyed():SurfaceView的holder被销毁
4、创建MediaPlayer并与SurfaceView的holder被创建
MediaPlayer mediaPlayer = new MediaPlayer();mediaPlayer.setDataSource("SD卡的路径");mediaPlayer.setDisplay(holder);mediaPlayer. prepareAsync ();
mediaPlayer.start();
这里使用mediaPlayer.setDisplay(holder);将播放的视频显示在SurfaceView的容器holder中。并且视频一般很大,因此都需要使用prepareAsync()异步准备
先看一下代码:
import java.io.IOException;import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.LinearLayout;public class ThreeKindsVideoActivity extends Activity implements SurfaceHolder.Callback,OnPreparedListener{/** Called when the activity is first created. */SurfaceHolder surfaceHolder;SurfaceView surfaceView;MediaPlayer mediaPlayer;Display current;int videoHeight;int videoWidth;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);surfaceView = (SurfaceView) findViewById(R.id.surfaceView);current = getWindowManager().getDefaultDisplay();//获取设备的尺寸 SurfaceHolder surfaceHolder = surfaceView.getHolder();// 找到容器SurfaceHolder surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 创建一个缓冲区,为了看视频不卡顿surfaceHolder.addCallback(this);// 添加SurfaceHolder的回调函数,类似于监听,所以需要添加实现接口的方法SurfaceHolder.Callback}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {// TODO 自动生成的方法存根}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO 自动生成的方法存根String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/auqi.3gp";@Override
public void onPrepared(MediaPlayer mp) {
// TODO 自动生成的方法存根
/* // 在播放之前,设置surface的大小与视频尺寸大小匹配
// 首先获取视频的尺度
videoHeight = mediaPlayer.getVideoHeight();
videoWidth = mediaPlayer.getVideoWidth();
// 如果视频的宽度或高度大于显示器的高度,找一个合理的比例进行缩放
if (videoHeight > current.getHeight()
|| videoWidth > current.getWidth()) {
// 获取视频与显示器的比例
float heightRatio =(float)videoHeight/(float) current.getHeight();
float widthRatio = (float) videoWidth / (float) current.getWidth();
// 我们按较大的尺寸缩放,主要保证视频的尺寸在显示范围内
if (heightRatio > 1 || widthRatio > 1) {
if (widthRatio > heightRatio) {
videoWidth = (int) Math.ceil((float)videoWidth / (float)widthRatio);
videoHeight = (int) Math.ceil((float)videoHeight / (float)widthRatio);
}else {
videoWidth = (int) Math.ceil((float)videoWidth / (float)heightRatio);
videoHeight = (int) Math.ceil((float)videoHeight / (float)heightRatio);
}
}
}//videoWidth,videoHeight是缩放后的尺寸,根据这个尺寸来制作显示Surface的大小
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth, videoHeight));*/
mediaPlayer.start();
}
Log.i("mwijfd没撒扩大 萨达萨达", "mwijfd没撒扩大 萨达萨达");try {mediaPlayer=new MediaPlayer();mediaPlayer.setDataSource(path);} catch (IllegalArgumentException e) {// TODO Auto-generated catch block//finish();// 此次有异常最好finish一下e.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}Log.i("mwijfd没撒扩大 萨达萨达", "mwijfd没撒扩大 萨达萨达");mediaPlayer.setDisplay(surfaceHolder);// 通过容器将SurfaceView与MediaPlayer进行关联mediaPlayer.prepareAsync();//将播放的视频显示在SurfaceView的容器holder中。并且视频一般很大,因此都需要使用prepareAsync()异步准备}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO 自动生成的方法存根}@Overridepublic void onPrepared(MediaPlayer mp) {// TODO 自动生成的方法存根<span style="color:#ff0000;">/* // 在播放之前,设置surface的大小与视频尺寸大小匹配// 首先获取视频的尺度videoHeight = mediaPlayer.getVideoHeight();videoWidth = mediaPlayer.getVideoWidth();// 如果视频的宽度或高度大于显示器的高度,找一个合理的比例进行缩放if (videoHeight > current.getHeight()|| videoWidth > current.getWidth()) {// 获取视频与显示器的比例float heightRatio =(float)videoHeight/(float) current.getHeight();float widthRatio = (float) videoWidth / (float) current.getWidth();// 我们按较大的尺寸缩放,主要保证视频的尺寸在显示范围内if (heightRatio > 1 || widthRatio > 1) {if (widthRatio > heightRatio) {videoWidth = (int) Math.ceil((float)videoWidth / (float)widthRatio);videoHeight = (int) Math.ceil((float)videoHeight / (float)widthRatio);}else {videoWidth = (int) Math.ceil((float)videoWidth / (float)heightRatio);videoHeight = (int) Math.ceil((float)videoHeight / (float)heightRatio);}}}//videoWidth,videoHeight是缩放后的尺寸,根据这个尺寸来制作显示Surface的大小surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth, videoHeight));*/</span>mediaPlayer.start();}
}
注意部分onPrepared()中的内容 如果不是正规用途就没必要写,因为这部分是为了调整视频的大小和播放器的大小相匹配而写的代码
Android多媒体详解相关推荐
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- 【转】Android菜单详解——理解android中的Menu--不错
原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...
- Android菜单详解——理解android中的Menu
前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...
- Android LayoutInflater详解
Android LayoutInflater详解 在实际开发中LayoutInflater这个类还是非常有用的,它的作用类 似于findViewById().不同点是LayoutInflater是用来 ...
- android Fragments详解
android Fragments详解一:概述 android Fragments详解二:创建Fragment 转载于:https://my.oschina.net/liangzhenghui/blo ...
- android WebView详解,常见漏洞详解和安全源码(下)
上篇博客主要分析了 WebView 的详细使用,这篇来分析 WebView 的常见漏洞和使用的坑. 上篇:android WebView详解,常见漏洞详解和安全源码(上) 转载请注明出处:http ...
- android WebView详解,常见漏洞详解和安全源码(上)
这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析. 由于博客内容长度,这次将分为上下两篇,上篇详解 WebView ...
- android子视图无菜单,Android 菜单详解
Android中菜单分为三种,选项菜单(OptionMenu),上下文菜单(ContextMenu),子菜单(SubMenu) 选项菜单 可以通过两种办法增加选项菜单,一是在menu.xml中添加,该 ...
- Android StateFlow详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121913352 本文出自[赵彦军的博客] 文章目录 系列文章 一.冷流还是热流 S ...
- Android SharedFlow详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121911675 本文出自[赵彦军的博客] 文章目录 系列文章 什么是SharedF ...
最新文章
- linux 物理内存统计,说说free命令 + Linux可用内存统计方法
- mysql实时物化到clickhouse(MaterializeMySQL)
- 用尽洪荒之力整理的Mysql数据库32条军规
- Dom4j完整教程~DOM4J简介
- html中contentEditable属性
- grpc-go客户端源码分析
- Java 中 notify 和 notifyAll 有什么区别?
- [Angular 6] 初学angular,环境全部最新,[ ng serve ] 不能启动,卡在 95% 不动 => 解决方案
- ios定位权限plist_iOS(定位一)后台定位和前台定位权限设置
- 小狼毫 Rime 输入法任务导向式常用参数修改指南
- Win10 安装 PySC2 环境 -- DeepMind联合战网开发的《星际争霸 II》强化学习环境
- Civil 3D菜单栏不在了怎么办
- 淘宝店铺商品接口 item_search_shop数据获取、拼多多关键词、1688原数据接口、淘宝商品详情sku信息等各大电商平台接口采集调用展示
- 数据挖掘与数据分析的区别
- Linux-QT5.9学习笔记——事件
- 【R语言】多模型综合——CLS(GRS)加权平均法的实现
- java string长度字节_java String类型数据的字节长度
- Servlet--转发和重定向
- 电脑防止锁屏JS代码
- 供独立游戏开发者参考的2D美工教程(一)