¡Acostúmbrate a escribir juntos! Este es el segundo día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .
prefacio
Después de la implementación del MediaPlayer
uso simple, todavía hay muchos problemas en el desarrollo real. Aquí, los problemas se resumen para registrar las razones y soluciones. Es un resumen del desarrollo.
Resumen de problemas
Consulta de información de recursos de TrackInfo
prepareAsync
Obtenga el recurso TrackInfo en el método de devolución de llamada después de cargar el recurso y ejecutar el método durante el desarrollo. Originalmente se esperaba obtener información de tamaño de video a través de este método, por ejemplo, para obtener información de recursos a MediaExtractor
través de un método . El objeto se puede obtener internamente , pero en el código fuente real, se encontrará que el retorno está vacío.getTrackFormat
TrackInfo
MediaFormat
MediaFormat
public MediaFormat getFormat() {
if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
|| mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
return mFormat;
}
return null;
}
复制代码
Por lo tanto, si MediaPlayer
el archivo de recursos no se puede obtener directamente mediante estimación interna, solo se puede obtener MediaExtractor
externamente.
el inicio falla después de la pausa
En el MediaPlayer
diagrama de secuencia se puede ver que se llama al método, si se llama no hay problema en pause
volver a llamarlo. start
Si el tiempo está en stop
, el método debe volver a ejecutarse prepare
para esperar a que el recurso se vuelva a preparar antes de jugar.
- Pregunta 1
El problema encontrado en el desarrollo real es que cuando el reproductor está Activity
en segundo plano, Activity
el método del ciclo de vida se llama onStop
, porque MediaPlayer
el ciclo de vida y la página están vinculados y también se llaman stop
. Finalmente, sé dónde está el motivo . MediaPlayer
Actualmente se encuentra en el stop
estado, por lo que tengo que reproducirlo para el método de MediaPlayer
ejecución .prepare
El problema 1 es resolver el problema de que el jugador puede reproducir el recurso después de regresar al fondo, pero el enlace SurfaceView
es una pantalla negra.
- Pregunta 2
La situación de la pantalla negra vinculante SurfaceView
es esencialmente similar a la pregunta 1. Debido a que SurfaceView
también hay un ciclo de vida, cuando se Activity
llama en segundo plano surfaceDestroyed
, la SurfaceView
vinculación original con el reproductor Surface
ha caducado y debe volver a vincularse.
La lógica original es post
inicializar y enlazar solo una vez en el método, por lo que parece post
inapropiado enlazar solo en el método.
surfaceView.post(new Runnable() {
@Override
public void run() {
AndroidMediaPlayer.Builder builder = new AndroidMediaPlayer.Builder(TestSimpleMediaPlayerActivity.this,uri,listener);
builder.withSurface(surfaceView.getHolder().getSurface());
androidMediaPlayer = builder.createPlayer();
androidMediaPlayer.prepareAsync();
}
});
复制代码
El trabajo de enlace se realiza desde surfaceView
el método de devolución de llamada de , para garantizar que el enlace se pueda actualizar cada vez que se ingrese a la página desde el fondo.surfaceCreated
Surface
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
if(androidMediaPlayer != null)
androidMediaPlayer.setSurface(surfaceView.getHolder().getSurface());
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
Log.d("<> surfaceView","surfaceChanged");
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
Log.d("<> surfaceView","surfaceDestroyed");
}
});
复制代码
- Pregunta 3
MediaPlayer
Otro problema es que no se proporciona una interfaz de devolución de llamada de progreso de reproducción. Aunque MediaPlayer
existe un getCurrentPosition
método para obtener el progreso de reproducción actual, no se puede encapsular para brindar la capacidad de obtener acceso en tiempo real, por lo que los desarrolladores deben implementar el método de acceso en tiempo real por sí mismos.
El valor de milisegundos de reproducción actual se puede obtener Thread
llamando continuamente al getCurrentPosition
método del jugador en un bucle.Además, se puede agregar el procesamiento de demora de acuerdo con las necesidades comerciales reales.
private class PlayerThread extends Thread{
private boolean toGet = false;
public void startGet(){
toGet = true;
}
public void stopGet(){
toGet = true;
}
@Override
public void run() {
super.run();
while (toGet){
if(mMediaPlayer != null){
int position = mMediaPlayer.getCurrentPosition();
if(mListener != null){
playerInfo.playerProgress = position;
mListener.onPlayerInfoCallBack(playerInfo);
}
}
}
}
}
复制代码
Resumir
MediaPlayer
Aunque es simple de usar, aún se expondrán algunos detalles en el desarrollo de la implementación. Si realmente desea desarrollar e implementar la función completa del reproductor, aún necesita mejorar y considerar muchos escenarios funcionales, MediaPlayer
y todavía hay algunas capacidades subyacentes en las que puede profundizar.