我知道这个问题已经被问了很多次,可能似乎是几个问题堆集,但我觉得这是相关的,重要的是许多开发人员; 我需要创建一个背景音乐Service
,可以跨多个活动,为我的Android游戏应用程序时,结束该结束,在所有的下列情况暂停运行:
- 某
Activity
,有它自己的音乐开始。 (恢复时此Activity
完成,这恰好是一个AndEngine
活性。) - 主屏幕被按下,程序就转到后台,或者应用程序被终止。 当应用程序返回到前台简历。 需要使用的
onUserLeaveHint()
另一种有用的链接。 - 手机收到呼叫并中断应用程序。 当呼叫已被处理简历。 需要使用的
TelephonyManager
类似于此 。 - 屏幕被锁定。 (简历屏已经被解锁后)需要使用
ACTION_USER_PRESENT
,这似乎是 非常 有问题的 。 - 基本上,音乐暂停每当没有被示出的应用程序,或者当从#1的特殊活动正在向用户显示。
以上就是所有的东西,我需要和信息我是拼凑起来的。 我当前的代码基本上类似于此 。
我觉得奇怪的是, AndEngine
管理有没有这些问题与他们的音乐,也许看在源代码将帮助别人寻找一个答案。 我使用的是从谷歌代码的最后一个功能GLES1版本 。
我已经采取了看看下面的链接,以及如何建立一个好的音乐Service
:
- 停止后台音乐服务
- http://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-App
- Android的背景音乐服务
- 播放音乐BG穿越活动的Android
- http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion
我想解决方案Service
于:
- 尽量少用
BroadcastReceivers
,如果可能的Android清单添加/权限 - 自包含的,错误检查
其他注意事项
- 目前,所有需要背景音乐的所有活动扩展一个常见的特殊类。
- 音乐需要循环,但只运行一个单一的轨道。
感谢大家的时间提前! 祝您好运!
编辑 - 下面是代码片段,随意提高或忽略:
媒体播放器包装
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();
}
}
首先这里是一些代码。 下面我给大家一个解释。
public class MusicService extends Service {
// service binder
private final IBinder mBinder = new LocalBinder();
// music player controling game music
private static CarefulMediaPlayer mPlayer = null;
@Override
public void onCreate() {
// load music file and create player
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.title_music);
mediaPlayer.setLooping(true);
mPlayer = new CarefulMediaPlayer(mediaPlayer, this);
}
@Override
public void onDestroy() {
super.onDestroy();
}
// =========================
// Player methods
// =========================
public void musicStart() {
mPlayer.start();
}
public void musicStop() {
mPlayer.stop();
}
public void musicPause() {
mPlayer.pause();
}
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
}
活动:
public class StartupActivity extends Activity {
// bounded service
private static MusicService mBoundService;
// whetere service is bounded or not
private boolean mIsBound;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_startup);
doBindService();
// HOW TO WORK WITH THE SERVICE:
// call the following methods whenever
// you want to interact with you
// music player
// ===================================
// call this e.g. in onPause() of your Activities
StartupActivity.getService().musicPause();
// call this e.g. in onStop() of your Activities
StartupActivity.getService().musicStop();
// call this e.g. in onResume() of your Activities
StartupActivity.getService().musicStart();
}
@Override
public void onDestroy() {
super.onDestroy();
doUnbindService();
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
setService(((MusicService.LocalBinder) service).getService());
}
@Override
public void onServiceDisconnected(ComponentName className) {
setService(null);
}
};
private void doBindService() {
Intent service = new Intent(getBaseContext(), MusicService.class);
// start service and bound it
startService(service);
bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService() {
if (mIsBound) {
// Detach existing connection.
unbindService(mServiceConnection);
mIsBound = false;
}
}
public static MusicService getService() {
return mBoundService;
}
private static void setService(MusicService mBoundService) {
StartupActivity.mBoundService = mBoundService;
}
}
首先,你有哪些在后台运行的服务。 因为你没有此服务创建的MediaPlayer对象。 随着localBinder你可以在你的活动(IES)和访问它像一个正常的Java对象的服务绑定。 该活动我已经张贴bindes服务。 在它的onCreate()方法,你可以找到一种方法,如何与媒体播放器进行交互。 您可以将任何活动绑定到你的服务。
另一种解决方案:
public class CarefulMediaPlayer {
final SharedPreferences sp;
final MediaPlayer mp;
private boolean isPlaying = false;
private static CarefulMediaPlayer instance;
public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
this.mp = mp;
instance = this;
}
public static CarefulMediaPlayer getInstance() {
return instance;
}
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) {}
}
}
然后,你可以暂停,播放,并通过调用CarefulMediaPlayer.getInstance()停止音乐播放()。
我就是这么做的,我很高兴与结果:
第一次创建服务:
public class LocalService extends Service
{
// This is the object that receives interactions from clients. See RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
private MediaPlayer player;
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder
{
LocalService getService()
{
return LocalService.this;
}
}
@Override
public void onCreate()
{
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
@Override
public void onDestroy()
{
destroy();
}
@Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public void play(int res)
{
try
{
player = MediaPlayer.create(this, res);
player.setLooping(true);
player.setVolume(0.1f, 0.1f);
player.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void pause()
{
if(null != player && player.isPlaying())
{
player.pause();
player.seekTo(0);
}
}
public void resume()
{
try
{
if(null != player && !player.isPlaying())
{
player.start();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void destroy()
{
if(null != player)
{
if(player.isPlaying())
{
player.stop();
}
player.release();
player = null;
}
}
}
2,创建一个基本的活动,并延长在巫你所有的活动,你想从它播放背景音乐:
public class ActivityBase extends Activity
{
private Context context = ActivityBase.this;
private final int [] background_sound = { R.raw.azilum_2, R.raw.bg_sound_5 };
private LocalService mBoundService;
private boolean mIsBound = false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
doBindService();
}
@Override
protected void onStart()
{
super.onStart();
try
{
if(null != mBoundService)
{
Random rand = new Random();
int what = background_sound[rand.nextInt(background_sound.length)];
mBoundService.play(what);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
@Override
protected void onStop()
{
super.onStop();
basePause();
}
protected void baseResume()
{
try
{
if(null != mBoundService)
{
mBoundService.resume();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
protected void basePause()
{
try
{
if(null != mBoundService)
{
mBoundService.pause();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private ServiceConnection mConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder) service).getService();
if(null != mBoundService)
{
Random rand = new Random();
int what = background_sound[rand.nextInt(background_sound.length)];
mBoundService.play(what);
}
}
public void onServiceDisconnected(ComponentName className)
{
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;
if(null != mBoundService)
{
mBoundService.destroy();
}
}
};
private void doBindService()
{
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
Intent i = new Intent(getApplicationContext(), LocalService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService()
{
if (mIsBound)
{
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
@Override
protected void onDestroy()
{
super.onDestroy();
doUnbindService();
}
}
就是这样,现在你有背景声音中所有正在从ACTIVITYBASE延伸活动。
你甚至可以通过调用控制暂停/恢复功能basePause()/ baseResume()。
不要忘了在清单申报服务:
<service android:name="com.gga.screaming.speech.LocalService" />
在启动活动,我们都具有约束力和seperately启动服务。 这是错误的,因为服务将保持活动退出后运行,因为我们还没有叫stopService()的任何地方。 因此,作为绑定的服务已经是“ 自动创建 ”服务过的部分“startService(服务)”应该被删除。
请纠正我,如果没有人得到相反的结果
startService(service);// remove this part
bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);