Serviço abrangente de música à prova de falhas do Android em várias atividades

Eu sei que essa pergunta já foi feita muitas vezes e pode parecer um conglomerado de várias questões, mas eu sinto que ela é relevante e importante para muitos desenvolvedores; Eu preciso criar uma música de fundoService que pode ser executado em várias atividades do meu jogo Android que termina quando o aplicativo é encerrado e pausa em todas as circunstâncias a seguir:

Um certoActivity que tem sua própria música é iniciada. (Retomar quando issoActivity acabamentos. Isso acontece de ser umAndEngine atividade.)A tela inicial é pressionada e o aplicativo é em segundo plano ou o aplicativo é encerrado. Continua quando o aplicativo retorna ao primeiro plano. Requer o uso deonUserLeaveHint(). Outro link útil.O telefone recebe uma chamada e interrompe o aplicativo. Retoma quando a chamada foi tratada. Requer o uso deTelephonyManager igual aisto.A tela está bloqueada. (Retoma após a tela ter sido desbloqueada.) Requer o uso deACTION_USER_PRESENT, o que pareceestar muito problemático.Basicamente a música faz uma pausa sempre que o aplicativo não está sendo mostrado ou quando a atividade especial do # 1 está sendo mostrada ao usuário.

Acima está tudo o que eu preciso e as informações que eu juntei.Meu código atual basicamente se assemelhaisto.

Eu acho curiosoAndEngine não consegue ter nenhum desses problemas com suas músicas, então, talvez, procurar no código-fonte ajudaria alguém que estivesse procurando uma resposta. estou a usara última versão funcional GLES1 do Google Code.

Eu dei uma olhada nos links a seguir, bem como na criação de uma boa músicaService:

Parando o serviço de fundo musicalhttp://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-AppServiço de música de fundo do AndroidTocando Música BG Através de Atividades no Androidhttp://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion

Eu gostaria da soluçãoService para:

Minimize o uso deBroadcastReceivers e adições / permissões do manifesto do Android, se possívelAuto-contido e verificação de erros

Outras notas

Atualmente todas as atividades que requerem a música de fundo estendem uma classe especial comum.A música precisa de loop, mas só executa uma única faixa.

Obrigado a todos antes do tempo! Boa sorte!

Editar - Aqui estão os trechos de código, sinta-se livre para melhorar ou ignorar:

Wrapper do Media Player

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) {}
    }
}

Serviço de Música

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() {

    }
}

Classe de atividade base aprimorada

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();
    }

}

questionAnswers(3)

yourAnswerToTheQuestion