Servicio integral de música a prueba de fallas de Android en múltiples actividades

Sé que esta pregunta se ha formulado muchas veces antes y puede parecer un conglomerado de varias preguntas, pero creo que es relevante e importante para muchos desarrolladores; Necesito crear una música de fondo.Service que puede ejecutarse en varias actividades para mi juego de Android que finaliza cuando la aplicación finaliza y se detiene en todas las circunstancias siguientes:

Un ciertoActivity Que tiene su propia música se inicia. (Reanudar cuando estoActivity acabados Esto pasa a ser unAndEngine actividad.)Se presiona la pantalla de inicio y la aplicación queda en segundo plano, o se termina la aplicación. Se reanuda cuando la aplicación vuelve al primer plano. Requiere el uso deonUserLeaveHint(). Otro enlace útil.El teléfono recibe una llamada e interrumpe la aplicación. Se reanuda cuando la llamada ha sido tratada. Requiere el uso deTelephonyManager Similar aesta.La pantalla está bloqueada. (Se reanuda después de que la pantalla haya sido desbloqueada). Requiere el uso deACTION_USER_PRESENT, que pareceser muy problemático.Básicamente, la música se detiene cada vez que no se muestra la aplicación o cuando se muestra al usuario la actividad especial de # 1.

Arriba está todo lo que necesito y la información que he reunido.Mi código actual básicamente se pareceesta.

Me parece curioso queAndEngine se las arregla para no tener ninguno de estos problemas con su música, así que quizás buscar en el código fuente ayudaría a alguien que busca una respuesta. Estoy usandoLa última versión funcional de GLES1 de Google Code..

También he echado un vistazo a los siguientes enlaces para crear una buena música.Service:

Detener la música del servicio de fondohttp://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-AppServicio de música de fondo para AndroidReproducción de música BG a través de actividades en Androidhttp://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion

Me gustaria la solucionService a:

Minimizar el uso deBroadcastReceivers y adiciones / permisos del manifiesto de Android si es posibleAutocontenido y comprobación de errores.

Otras notas

Actualmente, todas las actividades que requieren la música de fondo extienden una clase especial común.La música necesita hacer un bucle pero solo corre una sola pista.

Gracias a todos por adelantado! ¡La mejor de las suertes!

Editar - Aquí hay fragmentos de código, siéntase libre de mejorar o ignorar:

Reproductor de medios Wrapper

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

Servicio de musica

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

    }
}

Clase de actividad base mejorada

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

}

Respuestas a la pregunta(3)

Su respuesta a la pregunta