Android音频使用总结
来源:互联网 发布:多条update sql语句 编辑:程序博客网 时间:2024/06/05 11:41
本文对Android音频播放做简单总结。
一.基本概念
(一)Android媒体格式
Android提供了对常用音频和视频格式的支持,它所支持的音频格式有MP3,3GP,OGG,和 WAVE(.ave)等,支持的视频格式有3GP和MPEG-4等,通过Android API提供的方法,可以实现音 频与视频的播放。
播放SD卡中的一个音频文件 ,注意权限的添加:
Android.permission.READ_EXTERNAL_STORAGE
(二)播放音频文件,一般使用的是:MediaPlayer类或SoundPool类。
二.MediaPlayer的使用总结
Media Player可以使用静态方法创建也可以使用无参构造的方法来创建。
(一)静态方法创建MediaPlayer对象
使用create方法来绑定资源
1.用于从资源ID对应的资源文件中装载音频,并返回新创建的MediaPlayer对象
MediaPlayer player=MediaPlayer.create(this,R.raw.d);
这里的资源文件是放在res/raw目录下的
2.用于根据指定的URI来装载音频,并返回新创建的MediaPlayer对象
MediaPlayer player=MediaPlayer.create(this,Uri,pares(“http://www.music.baidu.com/sou nd/mylove.mp3”));
但是,注意,这里的访问网络上的资源时,要在AndroidManifest.xml文件中授予该程序访问网络 的权限,具代码如下
(二)根据无参数的构造方法,创建MediaPlayer对象
用setDataSource()方法实现资源的绑定。
具体代码:
MediaPlayer player=new MediaPlayer(); player.setDataSource(“/sdcard/s.wav”); player.prepare();
使用构造方法创建的MediaPlayer必须预加载音频。才能去播放文件。
(三)MediaPlayer的常用方法
1.setDataSource() //设置 资源
2.start() throws IllegalStateException //开 始播放,如果没有预编译错过会报错
3.stop() //停 止播放
4.pause() //暂 停播放
5.prepare()//同步加载
6.prepareAsync()// 异步加载,完成后调用监听
7.isPlaying(); //本 地方法,判断播放状态
8.seekTo(int msec) //本地方法,跳转到时间点
9.int getDuration(); //本 地方法,获取音乐总长度
10.release() //释 放资源
11.reset() //重 置MediaPlayer
12.setLooping(boolean looping) //设 置循环
13.public native boolean isLooping(); //判 断循环状态
14.setVolume(float leftVolume, float rightVolume)
/ /设置音量,左声道和右声道
15.setVolume(float volume) //设 置音量
同步与异步的区别 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需 要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统 会通知进程进行处理,这样可以提高执行的效率。
(四)MediaPlayer的几个监听方式
1. 异步加载完成时回调监听
public void setOnPreparedListener(OnPreparedListener listener)
异步监听,一般在异步预加载之前就要设置好。
2.音乐播放完毕后回调监听
public void setOnCompletionListener(OnCompletionListener listener)
一般用于设置播放完毕后,播放下一首还是循环播放
3.当跳转完成时的监听
public void setOnSeekCompleteListener(OnSeekCompleteListener listener)
一般用于监听进度突然改变的值的变化
三.SoundPool的使用总结
由于MediaPlayer占用资源较高,且不支持同时播放多个音频,所有Android为我们提供了另一个播放音频的类SounePool.SoundPool也就是音频池,它可以同时播放多个短促的音频,而且占用的资源少,例如游戏中的多个音频同时播放。
Sound Pool的音频文件也是放在res/raw/文件夹下面
使用SoundPool播放音频的步骤如下:
(一)创建SoundPool对象
new SoundPool(int maxStreams,int streamType,int srcQuality)
其中,maxStreams用来指定可以容纳多少个音频,streamType用来指定声音类型,可以通过 AudioManager类提供的常量进行指定,通常使用STREAM_MUSIC; srcQuality参数用于指定音频的品质,0为默认
(二)加载所要播放的音频,四种方式
1. Public int load(Context context,int resid,int priority)
用于通过指定的资源来加载音频
2.Public int load(String path,int priority)
用于通过音频文件的路径来加载音频
3.Public int load(AssetFileDescriptor afd,int priority)
用于从AssetFileDescriptor所对应的文件中加载音频
4. Public int load(FileDescriptor fd,long offset,long length,int priority )
用于加载FileDescriptor对象中,从offset开始,长度为length的音频
(三)控制播放音频
play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
6个参数的说明:
1)soundID 用于指定要播放的音频,该音频为通过load()方法返回的音频
2)leftVolume 用于指定左声道的音量,取值为0-1.0
3)rightVolume 用于指定左声道的音量,取值为0-1.0
4) Priority 用于指定播放音频的优先级,数值越大,优先级越高
5)Loop 用于设置循环次数0为不循环-1为循环
6)Rate 用于指定速率,1为正常,最小值为0.5 最高值为2
上面就是Android音频使用的类和常用的方法,下面结合实际,做两个简单的示例。
四.使用MediaPlayer来控制文件的播放和停止
程序功能实现:
1.能播放固定的音频文件资源
2.能控制音频文件的暂停和停止,开始
3.能够使用进度拖动条来控制音频文件的播放
对于其他的一些复杂功能,暂时没有去实现。
这里的使用的是使用的静态方法和无参的构造方法来控制音频文件,实际应用中只使用一种就可以了。
本程序上面两个按钮和下面两个按钮不能混用,一次程序运行中只能使用静态或者无参的对象来控制音频文件,这里只为了对比功能才放到一起的。
(一)xml文件的设计
<?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" android:orientation="vertical" tools:context="com.lwz.mediaplayer.MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="音频播放" android:textSize="20sp" /> <SeekBar android:id="@+id/main_sb" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/main_tv_pro" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="00:00/00:00" android:textSize="15sp" /> <Button android:id="@+id/main_btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="start" android:text="播放" /> <Button android:id="@+id/main_btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="stop" android:text="停止" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#f00" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 动态使用音频对象" /> <Button android:id="@+id/main_btn_start2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="start2" android:text="播放" /> <Button android:id="@+id/main_btn_stop2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="stop2" android:text="停止" /></LinearLayout>
(二)java代码的设计
package com.lwz.mediaplayer;import android.app.Activity;import android.media.MediaPlayer;import android.os.Bundle;import android.os.Environment;/*** * 音频文件的使用 * 静态方法:播放的是程序本身的音频文件在/src/raw/文件夹下 * 动态方法:播放的是存储器的音频文件 */public class MainActivity extends Activity implements SeekBar.OnSeekBarChangeListener { //定义2个音频播放的对象 MediaPlayer mediaPlayer; MediaPlayer mediaPlayer2; //定义布局内的按钮控件 Button start; Button stop; Button start2; Button stop2; SeekBar seekBar; TextView tv_time; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //实例化布局内的控件 start = (Button) findViewById(R.id.main_btn_start); stop = (Button) findViewById(R.id.main_btn_stop); start2 = (Button) findViewById(R.id.main_btn_start2); stop2 = (Button) findViewById(R.id.main_btn_stop2); seekBar = (SeekBar) findViewById(R.id.main_sb); tv_time = (TextView) findViewById(R.id.main_tv_pro); //设置停止按钮点无效 stop.setEnabled(false); stop2.setEnabled(false); //给SeekBar设置监听事件 seekBar.setOnSeekBarChangeListener(this); } public void start(View v) { if (mediaPlayer == null) { //如果音频文件对象是空的就实例化数据 mediaPlayer = MediaPlayer.create(this, R.raw.arcs); //设置可以点击停止 stop.setEnabled(true); } //如果还没有开始播放,就播放音频,显示“暂停” if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); start.setText("暂停"); //开始计算 startTime(); //设置进度条的最大值 seekBar.setMax(mediaPlayer.getDuration() / 1000); //设置一直循环 mediaPlayer.setLooping(true); } else { //如果正在显示“暂停”时,单击暂停,就暂停音频,显示“播放” mediaPlayer.pause(); start.setText("播放"); //取消定时器 timer.cancel(); } } public void start2(View v) { if (mediaPlayer2 == null) { //如果音频文件对象是空的就实例化数据 //动态使用音频对象和静态使用使用区别的,这里直接new出来 mediaPlayer2 = new MediaPlayer(); try { //给音频对象设置资源地址 mediaPlayer2.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/laolang.mp3"); //这里要预加载 mediaPlayer2.prepare(); } catch (IOException e) { e.printStackTrace(); } //设置可以点击停止 stop2.setEnabled(true); } //如果还没有开始播放,就播放音频,显示“暂停” if (!mediaPlayer2.isPlaying()) { mediaPlayer2.start(); start2.setText("暂停"); //开始计算 startTime(); //设置进度条的最大值 seekBar.setMax(mediaPlayer2.getDuration() / 1000); //设置一直循环 mediaPlayer2.setLooping(true); } else { //如果正在显示“暂停”时,单击暂停,就暂停音频,显示“播放” mediaPlayer2.pause(); start2.setText("播放"); //取消定时器 timer.cancel(); } } /** * 时间开始跑 * 这里设置一个Timer对象来控制时间 */ Timer timer; //转换时间的一个对象 SimpleDateFormat format = new SimpleDateFormat("mm:ss"); private void startTime() { timer = new Timer(); //一秒之后每秒执行一次的任务 timer.schedule(new TimerTask() { @Override public void run() { //这里要在主线程执行 runOnUiThread(new Runnable() { @Override public void run() { //进度条每次加一 seekBar.setProgress(seekBar.getProgress() + 1); //获取当前播放的时间,单位毫秒秒 int time = seekBar.getProgress() * 1000; //把显示进度的文字显示到屏幕上 if(mediaPlayer2!=null) tv_time.setText(format.format(new Date(time)) + "/" + format.format(new Date(mediaPlayer2.getDuration()))); if(mediaPlayer!=null) tv_time.setText(format.format(new Date(time)) + "/" + format.format(new Date(mediaPlayer.getDuration()))); //结束后重新开始,进度条 if (seekBar.getProgress() == seekBar.getMax()) { seekBar.setProgress(0); } } }); } }, 1000, 1000); } public void stop(View v) { //这里是停止不是暂停 recyle(); } public void stop2(View v) { //这里是停止不是暂停 recyle2(); } /** * 彻底释放资源 */ public void recyle() { //判断非空才需做处理 if (mediaPlayer != null) { //保证音频停止 if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } //回收资源 mediaPlayer.release(); //设置对象为空 mediaPlayer = null; //设置显示文本为播放 start.setText("播放"); //设置禁止点击"停止" stop.setEnabled(false); } //取消时间计数器 timer.cancel(); //设置进度条的位置为开始的地方 seekBar.setProgress(0); } /** * 彻底释放资源 */ public void recyle2() { //判断非空才需做处理 if (mediaPlayer2 != null) { //保证音频停止 if (mediaPlayer2.isPlaying()) { mediaPlayer2.stop(); } //回收资源 mediaPlayer2.release(); //设置对象为空 mediaPlayer2 = null; //设置显示文本为播放 start2.setText("播放"); //设置禁止点击"停止" stop2.setEnabled(false); } //取消时间计数器 timer.cancel(); //设置进度条的位置为开始的地方 seekBar.setProgress(0); } @Override protected void onDestroy() { //页面关闭前先彻底释放音频的资源 recyle(); recyle2(); super.onDestroy(); } //定义一个布尔值判断是否是用户的操作的进度条 boolean fromUser; //当进度条发送生改变时回调 @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { this.fromUser = fromUser; } //进度条操作开始时回调 @Override public void onStartTrackingTouch(SeekBar seekar) { fromUser = false; } //进度条操作停止时回调 @Override public void onStopTrackingTouch(SeekBar seekBar) { //如果是用户拖动的进度条才做对应的时间跳转 if (fromUser) { //把音频播放时间设置到拖动的位置 int time = seekBar.getProgress() * 1000; if (mediaPlayer != null) { mediaPlayer.seekTo(time); } } }}
程序运行前要保证资源文件的存在;
这里音频文件的停止和退出页面一定要释放资源。
程序运行后的效果:
点击播放后效果:
播放时点击暂停,就停止音频播放,如图所示:
上面的动态使用音频对象功能也是一样的。
这里就可以实现对音频文件的基本控制了。
五.SoundPool播放音频的简单示例
本示例功能比较简单,根据五种小音频文件,对应的设置五个按钮来触发播放,程序中可以同时播放多个音频,比如上一个音频文件没有播放完,下一个音频文件也可以播放。
(一)xml布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="play" android:text="play" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="play1" android:text="play1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="play2" android:text="play2" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="play3" android:text="play3" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="play4" android:text="play4" /></LinearLayout>
(二)java代码文件
package com.lwz.soundpool;import android.media.AudioManager;import android.media.SoundPool;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import java.util.HashMap;/** * 使用SoundPool播放音频,可以同时播放多个音频 * 但是主要是播放时间比较短的音频 * 它的文件资源也是一般放在本地中 */public class MainActivity extends AppCompatActivity { SoundPool soundPool; //创建一个集合存放音频数据 HashMap<Integer, Integer> map = new HashMap<>(); /* 创建SoundPool对象 1. SoundPool(int maxStreams,int streamType,int srcQuality) 2. //其中,maxStreams用来指定可以容纳多少个音频,streamType用来指定声音类型,可以通过 AudioManager类提供的常量进行指定,通常使用STREAM_MUSIC; srcQuality参数用于指定 音频的品质,0为默认 * */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建音频对象 soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); //给集合设置数据 map.put(1, soundPool.load(this, R.raw.chimes, 100)); map.put(2, soundPool.load(this, R.raw.ding, 100)); map.put(3, soundPool.load(this, R.raw.enter, 100)); map.put(4, soundPool.load(this, R.raw.notify, 100)); map.put(5, soundPool.load(this, R.raw.ringout, 100)); } /* * play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) 2. 参数说明: 3. 参数 描述 4. soundID 用于指定要播放的音频,该音频为通过load()方法返回的音频 5. leftVolume 用于指定左声道的音量,取值为0-1.0 6. rightVolume 用于指定左声道的音量,取值为0-1.0 7. priority 用于指定播放音频的优先级,数值越大,优先级越高 8. loop 用于设置循环次数0为不循环-1为循环 9. rate 用于指定速率,1为正常,最小值为0.5 最高值为2 * */ public void play(View v) { soundPool.play(map.get(1), 1, 1, 100, 2, 1); } public void play1(View v) { soundPool.play(map.get(2), 1, 1, 100, 2, 1); } public void play2(View v) { soundPool.play(map.get(3), 1, 1, 100, 2, 1); } public void play3(View v) { soundPool.play(map.get(4), 1, 1, 100, 2, 1); } public void play4(View v) { soundPool.play(map.get(5), 1, 1, 100, 2, 1); } @Override protected void onDestroy() { super.onDestroy(); soundPool.release(); }}
程序运行后的结果:
这里没有办法展示声音效果!
对比这两个音频控制文件:
MediaPlayer是可以播放长时间的音频文件,Sound Pool是用来播放短时间的音频文件的;
Media Player和SoundPool控制的音频文件都可以放在资源文件夹res/raw/下面,也可以使用存储器中的音频资源文件,但是SoundPool控制的文件一般比较下,放在/raw目录中即可。
- Android音频使用总结
- Android音频总结
- Android MediaPlayer音频播放总结
- android使用MediaPlayer播放音频
- Android:使用MediaRecorder录制音频
- Android音频焦点AudioFocus使用
- Android 使用MediaPlayer播放音频
- Android 音频管理AudioManager使用
- android音频驱动学习问题与总结
- Linphone-Android + Freeswitch 音频电话会议测试总结
- android 音频播放总结 soundlPool,MediaPlay
- android 多媒体总结--音频相关(一)
- android 音频播放总结 soundlPool,MediaPlay
- 海思HI35XX之----音频模块使用总结
- iOS使用AudioToolbox接口开发音频总结
- 海思HI35XX之----音频模块使用总结
- Android 学习---音频学习 :SoundPool 音频池 的使用
- Android之多媒体--使用MediaPlayer播放音频
- 第9周项目4-广义表算法库及应用(2)
- Android 常用工作命令mmm,mm,m,croot,cgrep,jgrep,resgrep,godir
- 前端压缩图片以及php后端上传
- MySql -- cmd命令汇总
- containsAll方法
- Android音频使用总结
- 第十周-项目一 二叉树算法库
- Rdt(Reliable Data Transfer)可靠数据传输
- 音频知识
- 通过代码理解C++虚函数表和多态的实现
- applicationContext头文件解释
- 第十周项目1——二叉树算法库
- android蓝牙开发-与蓝牙模块通信
- 消费者消费行为研究