使用的时候是放在新开的线程中来播放音乐的,后来发现每次进入Activity后就会重复开始一个音乐播放的声音。为了避免重复开启播放功能我在原来代码的基础上增加了单例模式。这样就避免了出现重复播放。
Service 的重要概念如下:
1. Service 对象以 separated process 的方式执行,这表示 Service 与 UI(Activity)并不在同一个 process 里执行,而是各自在不同的 process 执行。
2. Android应用程序是在 Activity 启动与停止 Service。
3. 重载(override)onStart() 方法(method)在 Service 被启动,执行我们想要的背景功能。
4. 重载 onDestroy() 方法在 Service 被停止时,停止执行中的背景功能。
Android Service与Activity的不同:
1、onCreate和onStart是不同的:通过从客户端调用Context.startService(Intent)方法我们可以启动一个服务。如果这个服务还没有运行,Android将启动它并 且在onCreate方法之后调用它的onStart方法。如果这个服务已经在运行,那么它的onStart方法将被新的Intent再次调用。所以对于 单个运行的Service它的onStart方法被反复调用是完全可能的并且是很正常的。
2、不需要onResume、onPause以及onStop方法。
3、如果一个客户端需要持久的连接到一个服务,那么他可以调用 Context.bindService方法。如果这个服务没有运行方法将通过调用onCreate方法去创建这个服务但并不调用onStart方法来启 动它。相反,onBind方法将被客户端的Intent调用,并且它返回一个IBind对象以便客户端稍后可以调用这个服务。同一服务被客户端同时启动和 绑定是很正常的。
4、与Activity一样,当一个服务被结束是onDestroy方法将会被调 用。当没有客户端启动或绑定到一个服务时Android将终结这个服务。与很多Activity时的情况一样,当内存很低的时候Android也可能会终 结一个服务。如果这种情况发生,Android也可能在内存够用的时候尝试启动被终止的服务,所以你的服务必须为重启持久保存信息,并且最好在 onStart方法内来做。
其代码具体如下:
1 package com.liu.zhen.utils;
2
3 import android.content.Context;
4 import android.content.res.AssetFileDescriptor;
5 import android.media.MediaPlayer;
6 import android.util.Log;
7
8 /**
9 *
10 * This class is used for controlling background music
11 *
12 */
13 public class BackgroundMusic {
14 private static BackgroundMusic backgroundMusic = null;
15 private static final String TAG = "Bg_Music";
16 private float mLeftVolume;
17 private float mRightVolume;
18 private Context mContext;
19 private MediaPlayer mBackgroundMediaPlayer;
20 private boolean mIsPaused;
21 private String mCurrentPath;
22
23 private BackgroundMusic(Context context) {
24 this.mContext = context;
25 initData();
26 }
27
28 public static BackgroundMusic getInstance(Context context) {
29 if (backgroundMusic == null) {
30 backgroundMusic = new BackgroundMusic(context);
31 }
32 return backgroundMusic;
33 }
34
35 // 初始化一些数据
36 private void initData() {
37 mLeftVolume = 0.5f;
38 mRightVolume = 0.5f;
39 mBackgroundMediaPlayer = null;
40 mIsPaused = false;
41 mCurrentPath = null;
42 }
43
44 /**
45 * 根据path路径播放背景音乐
46 *
47 * @param path
48 * :assets中的音频路径
49 * @param isLoop
50 * :是否循环播放
51 */
52 public void playBackgroundMusic(String path, boolean isLoop) {
53 if (mCurrentPath == null) {
54 // 这是第一次播放背景音乐--- it is the first time to play background music
55 // 或者是执行end()方法后,重新被叫---or end() was called
56 mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
57 mCurrentPath = path;
58 } else {
59 if (!mCurrentPath.equals(path)) {
60 // 播放一个新的背景音乐--- play new background music
61 // 释放旧的资源并生成一个新的----release old resource and create a new one
62 if (mBackgroundMediaPlayer != null) {
63 mBackgroundMediaPlayer.release();
64 }
65 mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
66 // 记录这个路径---record the path
67 mCurrentPath = path;
68 }
69 }
70
71 if (mBackgroundMediaPlayer == null) {
72 Log.e(TAG, "playBackgroundMusic: background media player is null");
73 } else {
74 // 若果音乐正在播放或已近中断,停止它---if the music is playing or paused, stop it
75 mBackgroundMediaPlayer.stop();
76 mBackgroundMediaPlayer.setLooping(isLoop);
77 try {
78 mBackgroundMediaPlayer.prepare();
79 mBackgroundMediaPlayer.seekTo(0);
80 mBackgroundMediaPlayer.start();
81 this.mIsPaused = false;
82 } catch (Exception e) {
83 Log.e(TAG, "playBackgroundMusic: error state");
84 }
85 }
86 }
87
88 /**
89 * 停止播放背景音乐
90 */
91 public void stopBackgroundMusic() {
92 if (mBackgroundMediaPlayer != null) {
93 mBackgroundMediaPlayer.stop();
94 // should set the state, if not , the following sequence will be
95 // error
96 // play -> pause -> stop -> resume
97 this.mIsPaused = false;
98 }
99 }
100
101 /**
102 * 暂停播放背景音乐
103 */
104 public void pauseBackgroundMusic() {
105 if (mBackgroundMediaPlayer != null
106 && mBackgroundMediaPlayer.isPlaying()) {
107 mBackgroundMediaPlayer.pause();
108 this.mIsPaused = true;
109 }
110 }
111
112 /**
113 * 继续播放背景音乐
114 */
115 public void resumeBackgroundMusic() {
116 if (mBackgroundMediaPlayer != null && this.mIsPaused) {
117 mBackgroundMediaPlayer.start();
118 this.mIsPaused = false;
119 }
120 }
121
122 /**
123 * 重新播放背景音乐
124 */
125 public void rewindBackgroundMusic() {
126 if (mBackgroundMediaPlayer != null) {
127 mBackgroundMediaPlayer.stop();
128 try {
129 mBackgroundMediaPlayer.prepare();
130 mBackgroundMediaPlayer.seekTo(0);
131 mBackgroundMediaPlayer.start();
132 this.mIsPaused = false;
133 } catch (Exception e) {
134 Log.e(TAG, "rewindBackgroundMusic: error state");
135 }
136 }
137 }
138
139 /**
140 * 判断背景音乐是否正在播放
141 *
142 * @return:返回的boolean值代表是否正在播放
143 */
144 public boolean isBackgroundMusicPlaying() {
145 boolean ret = false;
146 if (mBackgroundMediaPlayer == null) {
147 ret = false;
148 } else {
149 ret = mBackgroundMediaPlayer.isPlaying();
150 }
151 return ret;
152 }
153
154 /**
155 * 结束背景音乐,并释放资源
156 */
157 public void end() {
158 if (mBackgroundMediaPlayer != null) {
159 mBackgroundMediaPlayer.release();
160 }
161 // 重新“初始化数据”
162 initData();
163 }
164
165 /**
166 * 得到背景音乐的“音量”
167 *
168 * @return
169 */
170 public float getBackgroundVolume() {
171 if (this.mBackgroundMediaPlayer != null) {
172 return (this.mLeftVolume + this.mRightVolume) / 2;
173 } else {
174 return 0.0f;
175 }
176 }
177
178 /**
179 * 设置背景音乐的音量
180 *
181 * @param volume
182 * :设置播放的音量,float类型
183 */
184 public void setBackgroundVolume(float volume) {
185 this.mLeftVolume = this.mRightVolume = volume;
186 if (this.mBackgroundMediaPlayer != null) {
187 this.mBackgroundMediaPlayer.setVolume(this.mLeftVolume,
188 this.mRightVolume);
189 }
190 }
191
192 /**
193 * create mediaplayer for music
194 *
195 * @param path
196 * the path relative to assets
197 * @return
198 */
199 private MediaPlayer createMediaplayerFromAssets(String path) {
200 MediaPlayer mediaPlayer = null;
201 try {
202 AssetFileDescriptor assetFileDescritor = mContext.getAssets()
203 .openFd(path);
204 mediaPlayer = new MediaPlayer();
205 mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(),
206 assetFileDescritor.getStartOffset(),
207 assetFileDescritor.getLength());
208 mediaPlayer.prepare();
209 mediaPlayer.setVolume(mLeftVolume, mRightVolume);
210 } catch (Exception e) {
211 mediaPlayer = null;
212 Log.e(TAG, "error: " + e.getMessage(), e);
213 }
214 return mediaPlayer;
215 }
216 }
如此,背景音乐播放已基本完成。