Pues la semana pasada me reportaron un BUG muy extraño en la que el UI se congelaba, simplemente estaba tocando un video y PUM! Esto sucedía de manera aleatoria en solo algunos dispositivos, y bueno para no hacerla larga (no vaya a ser que a alguien le guste, jejeje), resulto ser el media player server de android. Resulta que en algunas ocasiones simplemente la llamada a su metodo release() se atora, no mas no regresa. Y si, estoy hablando de android.media.MediaPlayer.
Despues de buscar en internet por alguna solución, lo unico que encontre fue el diagrama de estados, y bueno la recomendación fue checar mi aplicación y revisar que los cambios de estado esten implementados correctamente. He aqui una referencia a tal diagrama.
http://developer.android.com/reference/android/media/MediaPlayer.html
Y bueno no encontré ningun problema en la secuencia de hecho, ni la memoria se ve incrementada de una manera en la que pueda parecer que no se esta liberando, ni el procesador se ve muy cargado, simplemente algunas veces, en algunos dispositivos se congela.
Al final mi solución fue:
Dentro de la clase en la cual utilizo el media player, creo una clase interna que solo me va a servir para llamar al metodo release del media player
private class ReleaseCheck implements Runnable
{
public CLASE_EN_DONDE_SE_LLAMA_A_RELEASE m_JNIVideoClass;
/**
* Default constructor
* @param videoClass : The target object in which the MediaPlayer will be monitored.
*/
public ReleaseCheck(CLASE_EN_DONDE_SE_LLAMA_A_RELEASE videoClass)
{
m_JNIVideoClass = videoClass;
}
/**
* Waits one second, after that it check if the
* media server has been released, if not it kills it.
*/
public void run()
{
try
{
Thread.sleep(1000);
// is the media player still releasing
if (m_JNIVideoClass.m_Releasing)
{
// Kill media player
Log.e(TTMActivity.Instance().getTag(), "MediaPlayer : The media server must be killed...");
killMediaServer();
}
}
catch (Exception e)
{
Log.e(TTMActivity.Instance().getTag(), "Error in ReleaseCheck.run() : " + e.getMessage());
}
}
}
Ademas agregue dos metodos, KillMediaPLayer que simplemente le da un Kill al media player, y una verified release que inicia un thread que se encarga deverificar que realmente le media player se haya liberado, de lo contrario, lo apaga, lo mata, KILL!!!.
/**
* Stops the process /system/bin/mediaserver which is hanged, this is
* intended to avoid the device to get frozen, by media player not
* returning when calling the release method.
**/
public void killMediaServer()
{
try
{
Log.d(TTMActivity.Instance().getTag(), "Killing the media server.");
if (!SystemUtils.runProtectedCommand(TTMActivity.Instance().getTag() + " : Killing the media server",SU_KILL_COMMAND))
{
Log.e(TTMActivity.Instance().getTag(), "Cannot kill media server");
}
else
{
Log.e(TTMActivity.Instance().getTag(), "media server killed");
}
}
catch (Exception e)
{
Log.e(TTMActivity.Instance().getTag(), "Error killing the media server : " + e.getMessage());
}
}
/**
* Tries to release the media player for a new video or sound file.
* It starts a Thread which waits for the release function to end.
**/
protected void verifiedRelease()
{
// set the releasing flag
m_Releasing = true;
// Create and start the release wait thread
Thread t = new Thread(new ReleaseCheck(this));
t.start();
// Do the media player release
m_MediaPlayer.release();
m_MediaPlayer = null;
// turn of the release flag
m_Releasing = false;
}
Si alguien encuentra una solución mas elegante para esto, please no tuerza a la banda!
Saludos.
Increíble pero cierri
ReplyDelete