No se puede obtener android MediaPlayer onCompletion para disparar

Estoy tratando de usar la clase androide MediaPlayer para reproducir algunos sonidos.

Aquí está el código

MediaPlayer mp = new MediaPlayer(); mp.setDataSource(context, Uri.parse(soundUrl)); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); mp.setLooping(false); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.i(LOGTAG, "onComplete hit"); mp.stop(); mp.release(); } }); mp.prepare(); mp.start(); 

Este código se ejecuta en un servicio, pero por alguna razón el sonido se reproduce bien, pero cualquier cosa colocada en el onCompletion no parece disparar. Entonces consigo un mensaje en el logcat que el mediaplayer no fue lanzado. Estoy en una pérdida a lo que tengo mal con esto.

Estoy corriendo esta prueba en una galaxia nexo 4.0.4 stock rom.

También noto que el sonido puede ser recortado al final.

Aquí es cómo lo tengo:

  video.setOnCompletionListener(this); IntroClip.execute(video); } @Override public void onCompletion(MediaPlayer mp){ Button LoginButton; Button CreateAccount; Button RecoverPass; setContentView(R.layout.loginmenu); Spin = (ProgressBar)findViewById(R.id.Spinner); mp.release(); } 

Es realmente simple (pero tonto). Establezca su listener después de llamar a start (), así:

 ediaPlayer mp = new MediaPlayer(); mp.setDataSource(context, Uri.parse(soundUrl)); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); mp.setLooping(false); mp.prepare(); mp.start(); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.i(LOGTAG, "onComplete hit"); mp.stop(); mp.release(); } }); 

Estaba encontrando síntomas similares a esto, y la causa raíz era que el MediaPlayer estaba recibiendo la basura recogida antes de que se OnCompletionListener .

A juzgar por su código, parece que el mismo problema – su código no tiene una referencia de larga vida a la MediaPlayer, por lo que tan pronto como esa función termina (y antes de que el audio termina de jugar) el MediaPlayer es susceptible a GC.

Este problema es identificable por esta línea de registro:

 02-22 13:14:57.969: W/MediaPlayer-JNI(16888): MediaPlayer finalized without being released 

Puede solucionarlo reestructurando la clase de manera que la referencia MediaPlayer se mantenga durante más tiempo, almacenando una referencia a ella en la actividad y reutilizando la misma instancia para reproducir el mismo sonido varias veces, por ejemplo.

Hay una explicación más detallada aquí: Garbage Collection causas: MediaPlayer finalizado sin ser lanzado

Existen dos métodos para inicializar el objeto MediaPlayer, "new" y "create ()". Para hacer OnCompletionListener, es diferente para los objetos obtenidos en estos dos enfoques.

1) el "nuevo" enfoque

 MediaPlayer mp = new MediaPlayer(); mp.setDataSource(context, Uri.parse(soundUrl)); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); mp.setLooping(false); mp.prepare(); mp.start(); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.i(LOGTAG, "onComplete hit"); mp.stop(); mp.release(); } }); 

2) el método "create"

 MediaPlayer mp = MediaPlayer.create(getActivity(), Uri.parse(soundUrl)); //mp.prepare() is not needed here mp.setLooping(false); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ @Override public void onCompletion(MediaPlayer mp) { Log.i(LOGTAG, "onComplete hit"); mp.stop(); mp.release(); } }); 

Para el método create (), he experimentado el problema similar. Si mp.prepare () se llama después de llamar a create (), el procedimiento nunca alcanzará el setOnCompletionListener siguiente, ni siquiera a la start (). La razón esencial es que " los objetos están en el estado Preparado si la creación usando el método create tiene éxito " ( https://developer.android.com/reference/android/media/MediaPlayer.html ). Así que no necesita llamar a prepare () después de usar el método create ().

En realidad, la razón es que el MediaPlayer es una variable local. Una vez finalizada la función, el MediaPlayer es recogido por GC. Así que la solución es fácil, haga de su MediaPlayer un miembro de la clase.

 YourClassName { MediaPlayer mp = new MediaPlayer(); void YourFunction() { mp.setDataSource(context, Uri.parse(soundUrl)); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); mp.setLooping(false); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.i(LOGTAG, "onComplete hit"); mp.stop(); mp.release(); } }); mp.prepare(); mp.start(); } } 
  • Proguard rompe el archivo de audio en activos o en bruto
  • Mediaplayer responde al segundo clic para pausar
  • Android: Iniciar nueva actividad desde la clase de aplicación
  • Ni la pausa ni la parada funcionan mientras se reproduce RTSP con Android MediaPlayer
  • ExoPlayer y comandos start / pause / seekTo
  • Posición de control de vídeo de Android en Titanium
  • Reproductor de medios de Android con servicio
  • VideoView no se inicia cuando está invisible
  • Reproducción de archivos de audio uno tras otro
  • Cómo capturar una Excepción si la Internet o la señal está desactivada
  • Exoplayer tocando archivos m3u8 en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.