Android音频使用总结
本文对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文件的设计
<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;@Overrideprotected 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() {@Overridepublic void run() {//这里要在主线程执行runOnUiThread(new Runnable() {@Overridepublic 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);}@Overrideprotected void onDestroy() {//页面关闭前先彻底释放音频的资源recyle();recyle2();super.onDestroy();}//定义一个布尔值判断是否是用户的操作的进度条boolean fromUser;//当进度条发送生改变时回调@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {this.fromUser = fromUser;}//进度条操作开始时回调@Overridepublic void onStartTrackingTouch(SeekBar seekar) {fromUser = false;}//进度条操作停止时回调@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//如果是用户拖动的进度条才做对应的时间跳转if (fromUser) {//把音频播放时间设置到拖动的位置int time = seekBar.getProgress() * 1000;if (mediaPlayer != null) {mediaPlayer.seekTo(time);}}}
}
程序运行前要保证资源文件的存在;
这里音频文件的停止和退出页面一定要释放资源。
程序运行后的效果:
点击播放后效果:
播放时点击暂停,就停止音频播放,如图所示:
上面的动态使用音频对象功能也是一样的。
这里就可以实现对音频文件的基本控制了。
五.SoundPool播放音频的简单示例
本示例功能比较简单,根据五种小音频文件,对应的设置五个按钮来触发播放,程序中可以同时播放多个音频,比如上一个音频文件没有播放完,下一个音频文件也可以播放。
(一)xml布局文件
<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 map = new HashMap<>();/*创建SoundPool对象1. SoundPool(int maxStreams,int streamType,int srcQuality)2. //其中,maxStreams用来指定可以容纳多少个音频,streamType用来指定声音类型,可以通过AudioManager类提供的常量进行指定,通常使用STREAM_MUSIC; srcQuality参数用于指定音频的品质,0为默认* */@Overrideprotected 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.06. rightVolume 用于指定左声道的音量,取值为0-1.07. 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);}@Overrideprotected void onDestroy() {super.onDestroy();soundPool.release();}
}
程序运行后的结果:
这里没有办法展示声音效果!
对比这两个音频控制文件:
MediaPlayer是可以播放长时间的音频文件,Sound Pool是用来播放短时间的音频文件的;
Media Player和SoundPool控制的音频文件都可以放在资源文件夹res/raw/下面,也可以使用存储器中的音频资源文件,但是SoundPool控制的文件一般比较下,放在/raw目录中即可。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
