一. 前言

  1. MediaPlayer和SoundPool都是用来播放音频的。

  2. 一般大家使用的是MediaPlayer来播放音频,它的创建和销毁都是非常消耗资源的,如果我们的需求是播放一些短促而且频繁播放的音频的话MediaPlayer就有些不合适了,应该使用SoundPool来播放短促的音频。

二. MediaPlayer

常用于播放背景音乐

1. 单例工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
public class BackgroundMusicManager {
private static BackgroundMusicManager backgroundMusic = null;
private static final String TAG = "Bg_Music";
private float mLeftVolume;
private float mRightVolume;
private Context mContext;
private MediaPlayer mBackgroundMediaPlayer;
private boolean mIsPaused;
private int mCurrentPath;

//单例模式
private BackgroundMusicManager(Context context) {
this.mContext = context;
initData();
}
public static synchronized BackgroundMusicManager getInstance(Context context) {
if (backgroundMusic == null) {
backgroundMusic = new BackgroundMusicManager(context);
}
return backgroundMusic;
}

// 初始化一些数据
private void initData() {
mLeftVolume = 0.5f;
mRightVolume = 0.5f;
mBackgroundMediaPlayer = null;
mIsPaused = false;
mCurrentPath = 0;
}

/**
* 根据path路径播放背景音乐
*
* @param path
* :assets中的音频路径
* @param isLoop
* :是否循环播放
*/
public void playBackgroundMusic(int path, boolean isLoop) {
if (mCurrentPath == 0) {
// 这是第一次播放背景音乐--- it is the first time to play background music
// 或者是执行end()方法后,重新被叫---or end() was called
mBackgroundMediaPlayer = createMediaPlayerFromPath(path);
mCurrentPath = path;
} else {
if (mCurrentPath != path) {
// 播放一个新的背景音乐--- play new background music
// 释放旧的资源并生成一个新的----release old resource and create a new one
if (mBackgroundMediaPlayer != null) {
mBackgroundMediaPlayer.release();
}
mBackgroundMediaPlayer = createMediaPlayerFromPath(path);
// 记录这个路径---record the path
mCurrentPath = path;
}
}

if (mBackgroundMediaPlayer == null) {
Log.e(TAG, "playBackgroundMusic: background media player is null");
} else {
// 若果音乐正在播放或已近中断,停止它---if the music is playing or paused, stop it
mBackgroundMediaPlayer.stop();
mBackgroundMediaPlayer.setLooping(isLoop);
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e) {
Log.e(TAG, "playBackgroundMusic: error state");
}
}
}

/**
* 停止播放背景音乐
*/
public void stopBackgroundMusic() {
if (mBackgroundMediaPlayer != null) {
mBackgroundMediaPlayer.stop();
// should set the state, if not , the following sequence will be
// error
// play -> pause -> stop -> resume
this.mIsPaused = false;
}
}

/**
* 暂停播放背景音乐
*/
public void pauseBackgroundMusic() {
if (mBackgroundMediaPlayer != null
&& mBackgroundMediaPlayer.isPlaying()) {
mBackgroundMediaPlayer.pause();
this.mIsPaused = true;
}
}

/**
* 继续播放背景音乐
*/
public void resumeBackgroundMusic() {
if (mBackgroundMediaPlayer != null && this.mIsPaused) {
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
}
}

/**
* 重新播放背景音乐
*/
public void rewindBackgroundMusic() {
if (mBackgroundMediaPlayer != null) {
mBackgroundMediaPlayer.stop();
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e) {
Log.e(TAG, "rewindBackgroundMusic: error state");
}
}
}

/**
* 判断背景音乐是否正在播放
*
* @return:返回的boolean值代表是否正在播放
*/
public boolean isBackgroundMusicPlaying() {
boolean ret;
if (mBackgroundMediaPlayer == null) {
ret = false;
} else {
ret = mBackgroundMediaPlayer.isPlaying();
}
return ret;
}

/**
* 结束背景音乐,并释放资源
*/
public void end() {
if (mBackgroundMediaPlayer != null) {
mBackgroundMediaPlayer.release();
}
// 重新“初始化数据”
initData();
}

/**
* 得到背景音乐的“音量”
*
* @return
*/
public float getBackgroundVolume() {
if (this.mBackgroundMediaPlayer != null) {
return (this.mLeftVolume + this.mRightVolume) / 2;
} else {
return 0.0f;
}
}

/**
* 设置背景音乐的音量
*
* @param volume
* :设置播放的音量,float类型
*/
public void setBackgroundVolume(float volume) {
this.mLeftVolume = this.mRightVolume = volume;
if (this.mBackgroundMediaPlayer != null) {
this.mBackgroundMediaPlayer.setVolume(this.mLeftVolume,
this.mRightVolume);
}
}

/**
* create mediaplayer for music
*
* @param path
* the path relative to assets
* @return
*/
private MediaPlayer createMediaPlayerFromPath(int path) {
MediaPlayer mediaPlayer = MediaPlayer.create(mContext, path);

mediaPlayer.setVolume(mLeftVolume, mRightVolume);

return mediaPlayer;
}
}

2. 使用

1
2
3
4
5
6
7
8
9
//判断是否正在播放
if (!BackgroundMusicManager.getInstance(this).isBackgroundMusicPlaying()) {

//播放
BackgroundMusicManager.getInstance(this).playBackgroundMusic(
R.raw.bg_music,
true
);
}

3. 参考文章

工具类修改参考:android实现背景音乐播放

理解型文章参考:Android中实现播放背景音乐功能

三. SoundPool

常用于播放游戏音效

1. 工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class SoundPlayUtil {
//及时音频播放类
private SoundPool soundPool;

//声音大小
private float voice = 1;

//单例模式
private static SoundPlayUtil instance;
private SoundPlayUtil(Context context){
if (soundPool == null){
Log.d(Constant.TAG,"初始化及时播放音频类");
//设置同时播放流的最大数量
soundPool = new SoundPool.Builder().setMaxStreams(3).build();
//加载音频文件
soundPool.load(context,R.raw.game_victory,1); // 1 游戏闯关成功
soundPool.load(context,R.raw.game_default,1); // 2 游戏闯关失败
soundPool.load(context,R.raw.game_click_btn,1); // 3 点击按钮的音效
soundPool.load(context,R.raw.game_remove,1); // 4 消除宝可梦的音效
soundPool.load(context,R.raw.game_un_click,1); // 5 无法点击按钮的音效
}
}
public static synchronized SoundPlayUtil getInstance(Context context){
if (instance == null){
instance = new SoundPlayUtil(context);
}
return instance;
}

//播放指定音乐
public void play(int soundID){
soundPool.play(soundID,voice,voice,0,0,1);
}

//setter,getter
public float getVoice() {
return voice;
}

public void setVoice(float voice) {
this.voice = voice;
}
}

2. 使用

1
SoundPlayUtil.getInstance(getBaseContext()).play(3);

3. 参考文章

SoundPool构造方法被弃用解决方法参考:SoundPool构造方法被弃用后的解决方案

SoundPool播放没有声音的解决方法参考:[故障及解决]SoundPool没有声音

SoundPool播放声音的使用参考:Android SoundPool 的使用