本文共 6085 字,大约阅读时间需要 20 分钟。
SoundPool
SoundPool(声音池),所处于"android.media.SoundPool"包下,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU的资源占用量低、反应延迟小,并且可以加载多个音频到SoundPool中,通过资源ID来管理。另外SoundPool还支持执行设置声音的品质、音量、播放比率等参数。
SoundPool提供一个构造函数,以下是它的完整签名:
SoundPool(int maxStreams,int streamType,int srcQuality)
通过上面的构造函数即可完成SoundPool的初始化,第一个参数为音频池最多支持装载多少个音频,就是音频池的大小;第二个参数指定声音的类型,在AudioManager类中以常量的形式定义,一般指定为AudioManager.STREAM_MUSIC即可;第三个参数为音频的质量,默认为0,这个参数为预留参数,现在没有实际意义,为扩展预留字段,一般传0即可。
对于一个音频池,涉及到音频的加载、播放、暂停、继续、释放资源等操作,SoundPool也为我们提供了相应的方法,其底层也是用C++编写的native方法。以下介绍一些常用的SoundPool方法:
上面方法无疑Load()和play()是最重要的,Load()具有多种重载方法,从参数名就可以看出是什么意思。这里讲解一下play()方法,soundID参数为资源ID;leftVolume和rightVolume个参数为左右声道的音量,从大到小取0.0f~1.0f之间的值;priority为音频质量,暂时没有实际意义,传0即可;loop为循环次数,0为播放一次,-1为无线循环,其他正数+1为播放次数,如传递3,循环播放4次;rate为播放速率,从大到小取0.0f~2.0f,1.0f为正常速率播放。
在使用load()装载音频的时候需要注意,load()方法是一个异步的方法,也就是说,在播放音频的时候,很可能此段音频还没有装载到音频池中,这里可以借助SoundPool的一个装载完成的监听事件SoundPool.setOnLoadCompleteListener来保证装载完成在播放声音。SoundPool.setOnLoadCompleteListener()需要实现一个SoundPool.OnLoadCompleteListener接口,其中需要实现onLoadComplete()方法,一下是onLoadComplete()方法的完整签名:
onLoadComplete(SoundPool soundPool, int sampleId, int status)
使用SoundPool示例
上面已经介绍了SoundPool的使用所涉及到的内容,下面通过一个简单的示例来演示一下SoundPool的使用,播放的音频资源都是我从其他app中拷贝出来的,没有实际意义。示例中的注释写的比较全,这里不再累述了。
1 package cn.bgxt.soundpooldemo; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import android.media.AudioManager; 7 import android.media.SoundPool; 8 import android.media.SoundPool.OnLoadCompleteListener; 9 import android.os.Bundle;10 import android.app.Activity;11 import android.util.Log;12 import android.view.View;13 import android.view.View.OnClickListener;14 import android.widget.Button;15 import android.widget.Toast;16 17 public class MainActivity extends Activity {18 private Button btn_newqqmsg, btn_newweibontf, btn_newweibotoast;19 private SoundPool pool;20 private MappoolMap;21 22 @Override23 protected void onCreate(Bundle savedInstanceState) {24 super.onCreate(savedInstanceState);25 setContentView(R.layout.activity_main);26 btn_newqqmsg = (Button) findViewById(R.id.btn_newqqmsg);27 btn_newweibontf = (Button) findViewById(R.id.btn_newweibontf);28 btn_newweibotoast = (Button) findViewById(R.id.btn_newweibotoast);29 30 poolMap = new HashMap ();31 // 实例化SoundPool,大小为332 pool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);33 // 装载音频进音频池,并且把ID记录在Map中34 poolMap.put("newqqmsg", pool.load(this, R.raw.qqmsg, 1));35 poolMap.put("newweibontf", pool.load(this, R.raw.notificationsound, 1));36 poolMap.put("newweibotoast", pool.load(this, R.raw.newblogtoast, 1));37 38 pool.setOnLoadCompleteListener(new OnLoadCompleteListener() {39 40 @Override41 public void onLoadComplete(SoundPool soundPool, int sampleId,42 int status) {43 // 每次装载完成均会回调44 Log.i("main", "音频池资源id为:" + sampleId + "的资源装载完成");45 // 当前装载完成ID为map的最大值,即为最后一次装载完成46 if (sampleId == poolMap.size()) {47 Toast.makeText(MainActivity.this, "加载声音池完成!",48 Toast.LENGTH_SHORT).show();49 btn_newqqmsg.setOnClickListener(click);50 btn_newweibontf.setOnClickListener(click);51 btn_newweibotoast.setOnClickListener(click);52 // 进入应用播放四次声音53 pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 3,54 1.0f);55 }56 }57 });58 }59 60 private View.OnClickListener click = new OnClickListener() {61 62 @Override63 public void onClick(View v) {64 65 switch (v.getId()) {66 case R.id.btn_newqqmsg:67 if (pool != null) {68 pool.play(poolMap.get("newqqmsg"), 1.0f, 1.0f, 0, 0, 1.0f);69 }70 break;71 case R.id.btn_newweibontf:72 if (pool != null) {73 pool.play(poolMap.get("newweibontf"), 1.0f, 1.0f, 0, 0,74 1.0f);75 }76 break;77 case R.id.btn_newweibotoast:78 if (pool != null) {79 pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 0,80 1.0f);81 }82 break;83 default:84 break;85 }86 }87 };88 89 @Override90 protected void onDestroy() {91 // 销毁的时候释放SoundPool资源92 if (pool != null) {93 pool.release();94 pool = null;95 }96 super.onDestroy();97 }98 }
效果展示:
SoundPool使用的注意事项
因为SoundPool的一些设计上的BUG,从固件版本1.0开始就有些没有修复的,以后应该会慢慢修复。这里简单提一下:
总结
本篇博客介绍了SoundPool的使用,虽然SoundPool还有一些不足的地方,当时对于应用中一些简短的特效音,如按键音、短消息音,或者一些游戏中密集的声音,如射击的枪声,爆破的声音等。都是可以使用SoundPool的,效率会比使用MediaPlayer要高的多。
本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_SoundPool.html,如需转载请自行联系原作者