1.1、准备音频资源
将准备的音频文放入assets文件夹下或者res下的raw文件夹下:
-
assets下可以再新建文件夹批量加载,而raw只能同级存放单个加载;
-
在assets内部单个文件超过1m时可能存在bug,在raw资源目录下不会存在;
-
SoundPool的音频文件大小不能超过1M同时时间超过5-6秒可能会出错。
1.2、SoundPool的构造方法
SoundPool(int maxStreams, int streamType, int srcQuality)
-
参数maxStreams指定支持多少个声音,SoundPool对象中允许同时存在的最多的流的数量,该值太大就会报错AudioFlinger could not create track, status: -12 ,就听不到声音,可根据需求设定
-
参数streamType指定声音类型,可以在AudioManager中定义流类型为STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING,STREAM_MUSIC 和STREAM_ALARM四种类型。
-
参数srcQuality指定声音品质(采样率变换质量),一般直接设置为0!
运用方式:
private static final int MAX_SOUNDS = 1;
private SoundPool soundPool;
//第一个参数是可以支持的声音数量,第二个是声音类型,第三个是声音品质
soundPool = new SoundPool(MAX_SOUNDS, AudioManager.STREAM_MUSIC, 0);
但是上面的构造方法在api 21 被废弃了。API 21 以后使用SoundPool.Builder创建SoundPool对象实例:
private static final int MAX_SOUNDS = 1;
private SoundPool soundPool;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool.Builder().setMaxStreams(MAX_SOUNDS).build();
} else {
//第一个参数是可以支持的声音数量,第二个是声音类型,第三个是声音品质
soundPool = new SoundPool(MAX_SOUNDS, AudioManager.STREAM_MUSIC, 0);
}
1.3、加载音频资源
int load(Context context, int resId, int priority)
Load the sound from the specified APK resource.
从APK资源载入,resId:如音频文件 R.raw.xxx
int soundID = soundPool.load(appContext, R.raw.tip, 1);
int load(String path, int priority)
Load the sound from the specified path. 从音频文件路径加载
int load(AssetFileDescriptor afd, int priority)
Load the sound from an asset file descriptor.
从asset 文件中加载
AssetFileDescriptor fileDescriptor = assetManager.openFd("sounds/tip.mp3");
int soundId = soundPool.load(fileDescriptor, 1);
int load(FileDescriptor fd, long offset, long length, int priority)
Load the sound from a FileDescriptor.
如存放在sd卡中的音频 FileDescriptor从文件中加载
1.4、播放音频资源
play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
用法方式:
int streamId = soundPool.play(
soundID, //声音id
1, //左声道:0.0f ~ 1.0f
1, //右声道:0.0f ~ 1.0f
1, //播放优先级:0表示最低优先级
repeatTime, //循环模式:0表示循环一次,-1表示一直循环,其他表示数字+1表示当前数字对应的循环次
1);//播放速度:1是正常,范围从0~2
关于播放控制的几个重要方法
// 通过流id暂停指定音频播放
final void pause(int streamID)
//恢复指定音频播放
final void resume(int streamID)
//停止指定音频播放
final void stop(int streamID)
//卸载指定音频
final boolean unload(int soundID)
//暂停所有音频的播放
final void autoPause()
//恢复所有暂停的音频播放
final void autoResum()
//设置指定id的音频循环播放次数
final void setLoop(int streamID, int loop)
//设置加载监听(因为加载是异步的,需要监听加载,完成后再播放)
void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
//设置优先级(同时播放个数超过最大值时,优先级低的先被移除)
final void setPriority(int streamID, int priority)
//设置指定音频的播放速率,0.5~2.0(rate>1:加快播放,反之慢速播放)
final void setRate(int streamID, float rate)
//释放所有资源
final void release()
2、SoundPool的封装
SoundPool的封装
-
为了使我们的代码更加清晰,我们将创建一个类,用于在Activity/Fragment之外加载和播放我们的声音。
-
首先,我们创建一个名为SoundPlayer的类。我们需要一些方法来隐藏从外部类访问和加载声音文件的逻辑。
这是SoundPlayer的实现。您可以根据需要更改/添加一些代码,但这是基本要点。
完整代码如下:
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
import java.util.HashMap;
/**
-
本地提示音播放器
-
SoundPool用于播放声音短,文件小的音频,延时短
-
@author: heiyulong
-
@date: 2021/4/16
*/
public class SoundPlayer {
private static final String TAG = "SoundPlayer";
private static final int MAX_SOUNDS = 3;
private Context appContext;
private SoundPool soundPool;
private HashMap<Integer,Integer> soundMap = new HashMap<>();
public SoundPlayer(Context appContext) {
// 版本兼容
this.appContext = appContext;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool.Builder().setMaxStreams(MAX_SOUNDS).build();
} else {
//第一个参数是可以支持的声音数量,第二个是声音类型,第三个是声音品质
soundPool = new SoundPool(MAX_SOUNDS, AudioManager.STREAM_MUSIC, 0);
}
}
/**
-
播放音频
-
@param resId 音频文件 R.raw.xxx
-
@param repeatTime 循环模式:0表示循环一次,-1表示一直循环,其他表示数字+1表示当前数字对应的循环次
*/
public void play(int resId, int repeatTime) {
int soundID = soundPool.load(appContext, resId, 1);
// 该方法防止sample not ready错误
soundPool.setOnLoadCompleteListener((soundPool, sampleId, status) -> {
int streamId = soundPool.play(
soundID, //声音id
1, //左声道:0.0f ~ 1.0f
1, //右声道:0.0f ~ 1.0f
1, //播放优先级:0表示最低优先级
repeatTime, //循环模式:0表示循环一次,-1表示一直循环,其他表示数字+1表示当前数字对应的循环次
1);//播放速度:1是正常,范围从0~2
最后
本文在开源项目GitHub中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中...
目前已经更新的部分资料,需要的自己取: