Mediaplayer cortando el sonido demasiado pronto
Tengo dos dispositivos en los que puedo probar mi juego: Un celular Celluar (SCH-R880) y un Kindle Fire, el Kindle Fire es mucho más potente que el teléfono.
Tengo varios efectos de sonido cortos (Menos o aproximadamente 1 segundo). Para guardar en la memoria, carga, reproduce y suelto algunos de estos efectos de sonido. En el teléfono juegan (sobre todo) como se esperaba. En el Kindle Fire, sin embargo, son cortos. Los sonidos realmente cortos se cortan tan rápidamente que no escucho nada. Los que se cargan en la configuración y permanecen, sin embargo, jugar bien.
- Java.lang.IllegalStateException en el método MediaPlayer.isplaying ()
- ¿Cómo reanudar MediaPlayer en Android?
- La URL no se puede emitir a String
- Biblioteca de caché de audio progresiva para Android
- Decodificación del flujo de RTSP en directo: gran retraso de vídeo con MediaPlayer en Android
Alguien tiene alguna idea de lo que está pasando aquí? ¿De algún modo estoy liberando mis medios de comunicación demasiado pronto? A continuación se muestra un ejemplo de esto. En el teléfono oigo "Nivel dos!" Pero en el Kindle escucho algo como "Lev tw."
mpNum = null; try { switch (level) { case 2: mpNum = MediaPlayer.create(contxt, R.raw.l2); break; case 3: mpNum = MediaPlayer.create(contxt, R.raw.l3); break; case 4: mpNum = MediaPlayer.create(contxt, R.raw.l4); break; case 5: mpNum = MediaPlayer.create(contxt, R.raw.l5); break; case 6: mpNum = MediaPlayer.create(contxt, R.raw.l6); break; case 7: mpNum = MediaPlayer.create(contxt, R.raw.l7); break; case 8: mpNum = MediaPlayer.create(contxt, R.raw.l8); break; default: return; } MediaPlayer vLevel = MediaPlayer.create(contxt, R.raw.level); vLevel.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { mp.start(); } }); vLevel.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mpl) { mpNum.start(); mpl.release(); } }); mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mp.release(); } }); } catch (Exception e) {}
En un intento de tratar de solucionar esto, he intentado SoundPool, pero no funciona; No oigo nada. A continuación se muestra lo que hice para intentar reproducir la música con SoundPool:
SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100); soundPool.load(contxt, R.raw.song2, 1); AudioManager mgr = (AudioManager)contxt.getSystemService(Context.AUDIO_SERVICE); float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC); float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); float volume = streamVolumeMax; soundPool.play(1, volume, volume, 1, 5, 2);
ACTUALIZAR
He notado cuando un sonido que debe estar jugando (pero no) tiene este error que aparece:
AudioPolicyManager: stopOutput() oldDevice 2 AudioPolicyManager: [getDeviceForStrategy] strategy : 0,forceUse(0)
- IllegalStateException en MediaPlayer
- MediaPlayer onCompletion no se llama con precisión
- Notificar una vez que el audio ha terminado de reproducir
- Android: el proceso ha muerto
- Streaming de vídeos de Youtube
- Error Mediaplayer (-19,0) después de repetidas jugadas
- MediaPlayer de Android - setDataSource y lanzamiento - IllegalStateException
- MediaPlayer: utiliza el volumen del tono de llamada en lugar del volumen del medio
Tuve el mismo problema y de hecho fue un problema de recolector de basura! Si asigna la instancia del reproductor de medios a alguna variable local dentro de un método, la instancia ya no existe después de dejar ese método, por lo que GC puede eliminarlo aleatoriamente en cualquier momento.
Para evitar esto, debe mantener al menos un puntero en la instancia en otro lugar. He creado un conjunto estático para mantener todos los punteros, se ve así:
private static Set<MediaPlayer> activePlayers = new HashSet<MediaPlayer>();
A continuación, la creación del reproductor de medios es la siguiente:
MediaPlayer player = MediaPlayer.create(context, context.getResources().getIdentifier(id, "raw", pkg)); activePlayers.add(player); player.setOnCompletionListener(releaseOnFinishListener); player.start();
Donde releaseOnFinishListener es un oyente que libera al reproductor de medios al final igual que el tuyo pero también elimina el puntero del conjunto activePlayers:
MediaPlayer.OnCompletionListener releaseOnFinishListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mp.release(); activePlayers.remove(mp); } };
Espero que esto te ayude.
He leído que la clase SoundPool es más adecuada para sonidos cortos como este que MediaPlayer, pero probablemente no sea el problema. ( Aquí hay un enlace a un ejemplo de SoundPool).
¿También puede publicar el código para su controlador de clics?
Además, recomiendo en lugar de liberar y recuperar instancias de MediaPlayer, use una instancia de MediaPlayer y siga las secuencias típicas reset (), setDataSource (), prepare (), start () siempre que sea necesario volver a usarla. Será más eficiente que construir una nueva instancia cada vez. Es decir:
MediaPlayer mp = new MediaPlayer(); AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.sound1); mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(); mp.prepare(); mp.start(); //to reuse mp.reset(); afd = getResources().openRawResourceFd(R.raw.sound2); mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(); mp.prepare(); mp.start();
Así que tuve los mismos problemas en un proyecto y es porque en KindleFire los sonidos cortados antes de terminar para arreglar eso (con el lanzamiento) agregué un retraso en el lanzamiento:
mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { // Add a handler delay new Timer().schedule(new TimerTask() { @Override public void run() { mp.release(); } }, DELAY_TIME); } });
No es la mejor solución, pero creo que tal vez le ayudará.
Esto es extraño, y no es una buena solución, pero la única solución que he encontrado hasta ahora. Si mp.setOnPreparedListener
y mp.setOnCompletionListener
y sólo tiene mp.start()
, funciona.
Tuve este problema y lo solucioné haciendo mi objeto MediaPlayer privado, por lo que el recolector de basura no limpia la instancia. Espero que ayude a alguien!
- Cómo detener la depuración sin cerrar la aplicación en Android Studio 2
- Android Espresso: Ejecución de múltiples pruebas secuencialmente