我知道这个问题之前已经被问过很多次,并且可能看起来是几个问题的集合,但我觉得它对许多开发人员来说是相关和重要的;我需要Service
为我的 Android 游戏创建一个可以跨多个活动运行的背景音乐,该音乐在应用程序终止时结束并在以下所有情况下暂停:
- 一个
Activity
有自己的音乐的人开始了。(Activity
完成后继续。这恰好是一个AndEngine
活动。) - 按下主屏幕并且应用程序在后台运行,或者应用程序被终止。当应用程序返回前台时恢复。需要使用
onUserLeaveHint()
. 另一个有用的链接。 - 手机接听电话并中断应用程序。呼叫处理完毕后恢复。需要使用
TelephonyManager
类似this。 - 屏幕被锁定。(解锁屏幕后恢复。) 需要使用,这
ACTION_USER_PRESENT
似乎很 成问题。 - 基本上,只要未显示应用程序或向用户显示来自#1 的特殊活动,音乐就会暂停。
以上是我需要的所有内容以及我拼凑的信息。我当前的代码基本上类似于this。
我觉得很好奇AndEngine
他们的音乐没有这些问题,所以也许查看源代码会帮助人们寻找答案。我正在使用来自 Google Code 的最后一个功能 GLES1 版本。
我还查看了以下链接以创建好音乐Service
:
- 停止后台服务音乐
- http://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-App
- 安卓背景音乐服务
- 在 Android 中跨活动播放 BG 音乐
- http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion
我希望解决方案Service
:
- 如果可能,尽量减少使用
BroadcastReceivers
Android Manifest 添加/权限 - 自包含和错误检查
其他注意事项
- 目前所有需要背景音乐的活动都扩展了一个通用的特殊类。
- 音乐需要循环播放,但只运行一首曲目。
提前感谢大家!祝你好运!
编辑 - 以下是代码片段,请随时改进或忽略:
媒体播放器包装
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import android.util.Log;
public class CarefulMediaPlayer {
final SharedPreferences sp;
final MediaPlayer mp;
private boolean isPlaying = false;
public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
this.mp = mp;
}
public void start() {
if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) {
mp.start();
isPlaying = true;
}
}
public void pause() {
if (isPlaying) {
mp.pause();
isPlaying = false;
}
}
public void stop() {
isPlaying = false;
try {
mp.stop();
mp.release();
} catch (final Exception e) {}
}
}
音乐服务
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
public class MusicService extends Service {
static CarefulMediaPlayer mPlayer = null;
@Override
public IBinder onBind(final Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
final MediaPlayer mp = MediaPlayer.create(this, R.raw.title_music);
mp.setLooping(true);
mPlayer = new CarefulMediaPlayer(mp,this);
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
mPlayer.start();
return 1;
}
@Override
public void onStart(final Intent intent, final int startId) {
}
public IBinder onUnBind(final Intent arg0) {
return null;
}
public static void onStop() {
mPlayer.stop();
}
public static void onPause() {
if (mPlayer!=null) {
mPlayer.pause();
}
}
public static void onResume() {
if (mPlayer!=null) {
mPlayer.start();
}
}
@Override
public void onDestroy() {
mPlayer.stop();
mPlayer = null;
}
@Override
public void onLowMemory() {
}
}
改进的基础活动类
import android.app.Activity;
import android.content.Intent;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
public abstract class BetterActivity extends Activity {
private boolean isHome = true;
@Override
protected void onResume() {
System.gc();
super.onResume();
MusicService.onResume();
isHome = true;
}
@Override
protected void onPause() {
if (((TelephonyManager)getSystemService(TELEPHONY_SERVICE)).getCallState()==TelephonyManager.CALL_STATE_RINGING
|| !((PowerManager)getSystemService(POWER_SERVICE)).isScreenOn()) {
MusicService.onPause();
}
super.onPause();
System.gc();
}
@Override
public boolean onKeyDown (final int keyCode, final KeyEvent ke) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
isHome = false;
default:
return super.onKeyDown(keyCode, ke);
}
}
@Override
public void startActivity(final Intent i) {
isHome = false;
super.startActivity(i);
}
@Override
protected void onUserLeaveHint() {
if (isHome) {
MusicService.onPause();
}
super.onUserLeaveHint();
}
}